Python的代码风格由PEP 8描述。这个文档描述了Python编程风格的方方面面。在遵守这个文档的条件下,不同程序员编写的Python代码可以保持最大程度的相似风格。这样就易于阅读,易于在程序员之间交流。
我们大家在学习Python的时候,好像很多人都不理解为什么在方法(方法)前面会加好几个下划的线,有时甚至两边都会加,比如像__this__这种。在我看到上面的文章之前,我一直以为Python中这些下划线的作用就像Golang中方法/函数的大小写一样,或是一些其他语言中的私人,公共的作用一样,但仔细深究,这不全是Python这样设计的初衷。
下面我们具体分析,话不多说了,来一起看看吧。
我们经常看到方法或者属性前面加了单下划线,并认为它表示该方法或者属性是该类型(Python和Golang一样,不光类可以有方法,很多类型甚至基本类型也可以定义方法)的私有方法或属性。但其实在Python中不存在真正意义上的私有方法或者属性,前面加单下划线_只是表示你不应该去访问这个方法或者属性,因为它不是API的一部分。
<强> 举个例子: >强
<前> class 标识(StrAndUnicode): ,,,… ,,,, ,,,def _get_errors(自我): ,,,,,,,“Returns an ErrorDict for 从而data provided for 从而form" ,,,,,,,if self._errors is 没有: ,,,,,,,,,,,self.full_clean () ,,,,,,,,,,,return self._errors ,,,errors =,财产(_get_errors) >之前该代码片段来自Django源码(Django/形式/forms.py)。这段代码的设计就属是错误性是对外API的一部分,如果你想获取错误详情,应该访问错误属性,而不是(也不应该)访问_get_errors方法。
<强> 双下划线开的头 >强
之前很多人跟我说Python中双下划线开头表示私有,我在很多地方也见到这样的说法。这样理解可能也不能说错,但这不是Python设计双下划线开头的初衷和目的,Python设计此的真正目的仅仅是为了避免子类覆盖父类的方法。
我们看个例子:
<前> class (对象): ,,,def __method(自我): ,,,,,,,印刷(“我# 39;m a method 拷贝class A") ,,,def method_x(自我): ,,,,,,,印刷(“我# 39;m another method 拷贝class \ n") , ,,,def 方法(自我): ,,,,,,,self.__method () ,,,,,,,self.method_x () class B (A): ,,,def __method(自我): ,,,,,,,印刷(“我# 39;m a method 拷贝class B") , ,,,def method_x(自我): ,,,,,,,印刷(“我# 39;m another method 拷贝class B \ n") if __name__ ==, & # 39; __main__ # 39;: ,,,print (“situation  1:“) ,,,a =, () ,,,a.method () ,,,, ,,,b =, B () ,,,b.method () ,,,, ,,,print (“situation 2:“) ,,,# a.__method () ,,,a._A__method () >之前<前> situation 1: 我# 39;m a  method class 一个拷贝 我# 39;m another  method class 一个拷贝 , 我# 39;m a  method class 一个拷贝 我# 39;m  another method 拷贝class B , situation 2: 我# 39;m a  method class 一个拷贝 >之前
<强> 这里有两个点需要注意: >强
https://www.python.org/dev/peps/pep-0008/method-names-and-instance-variables
前面我们就说了,Python中不存在真正意义上的私有变量。对于双下划线开头的方法和属性虽然我们不能直接引用,那是因为Python默认在其前面加了前缀_类名,所以就像2情况下面的代码,虽然我们不能用一个直接访问__method(),但却可以加上前缀去访问,即_A__method ()。
一般来说像__this__这种开头结尾都加双下划线的方法表示这是Python自己调用的,你不要调用。比如我们可以调用len()函数来求长度,其实它后台是调用了__len__()方法。一般我们应该使用兰,而不是直接使用__len__ ():