python的_xxx, __xxx, __xxx__区别
2017-05-18 14:55
127 查看
_xxx
弱“内部使用”标识如:”from M import *”,将不导入所有以下划线开头的对象,包括包、模块、成员。
表明该方法或属性不应该去调用
Python中不存在真正的私有方法。为了实现类似于c++中私有方法,可以在类的方法或属性前加一个“_”单下划线,意味着该方法或属性不应该去调用,它并不属于API。
xxx_
只是为了避免与python关键字的命名冲突__xxx
伪私有方法class A(object): def __init__(self): self.name = 'A' def __method(self): print("I'm a method in A") a = A() a.__method()
输出:
AttributeError: 'A' object has no attribute '__method'
虽然看上去在像是私有函数,在外部无法访问,但是其实python只是简单地给
__method()改了下名字,仍然可以这样访问:
a._A__method()
输出:
I'm a method in A
了解了这么一个改名的机制,再看下面这个例子:
class BaseClass(object): def __init__(self): self.name = 'Base' def __method(self): print("I'm Base") def method(self): self.__method() class SubClass(BaseClass): def __init__(self): super(SubClass, self).__init__() self.name = 'Sub' def __method(self): # 覆写父类__method() print("I'm Sub") def method(self): # 覆写父类method() self.__method() sub = SubClass() sub.method()
此时的输出为:
I'm Sub
没问题,子类覆写了父类的
method()方法,因此输出是”Sub”。如果不覆写:
class SubClass(BaseClass): def __init__(self): super(SubClass, self).__init__() self.name = 'Sub' def __method(self): # 覆写父类__method() print("I'm Sub") #def method(self): 没有覆写父类method() # self.__method()
调用
sub.method()时,输出:
I'm Base
可以发现,子类调用的是从父类继承下来的
method()方法,从而调用的自然是父类的
__method__()。
其实如果从改名的角度来思考,很容易理解。
在写每个类代码的时候,虽然我们写的都是:
def method(self): self.__method()
但是BaseClass直接把代码改成了:
def method(self): self._BaseClass__method()
对应着SubClass:
def method(self): self._SubClass__method()
而继承可以理解成,如果子类没有覆写,则复制父类的代码下来。因而就出现了,调用
sub.method()时,其实是调用了父类的
_BaseClass__method(),输出
BaseClass的情况。
为了加强继承的复制代码与改名机制的理解,我又写了如下代码
class BaseClass(object):
def __init__(self):
self.name = 'Base'
def __method(self):
print("I'm Base")
def method(self): self._BaseClass__method()
self._SubClass__method()
base = BaseClass()
base.method()
输出为:
I'm Base AttributeError: 'BaseClass' object has no attribute '_SubClass__method'
对于父类来说,它的类方法只有
_BaseClass__method(),因此调用
_SubClass__method()时报错。
接着,运行如下代码:
class BaseClass(object):
def __init__(self):
self.name = 'Base'
def __method(self):
print("I'm Base")
def method(self): self._BaseClass__method()
self._SubClass__method()
class SubClass(BaseClass):
def __init__(self):
super(SubClass, self).__init__()
self.name = 'Sub'
def __method(self):
print("I'm Sub")
sub = SubClass()
sub.method()
输出:
I'm Base I'm Sub
对子类来说,继承的时候首先复制了父类的代码,因此父类的
method()方法自然就被复制下来。然而,虽然父类的
__method()方法和子类的
__method()方法名字一样,但是由于改名机制的存在,其实两个函数的名字并不同,因此并不存在覆写的情况,而是SubClass不仅自己定义了一个
_SubClass__method(),同时复制了父类的
_BaseClass__method()。所以这里调用时输出是上面这样而不会报错。
__xxx__
“魔术”对象或属性许多特殊的代码会调用对应的魔术方法。下面是总结的部分我遇到过的魔术方法:
__init__()
这个很常见,就是创建一个类的实例的时候会调用,相当于构造函数。__call__()
如果一个类实现了这个函数,那么这个类就是“可调用对象”,可以通过如下方式调用:class C: def __call__(self, name): print(name) c = C() c('Hello!') # 会调用__call__()方法
输出:
Hello!
__getitem__()
class C: def __init__(self): self.list = [1,2,3,4,5] def __getitem__(self, item): return self.list[item] c = C() for i in range(5): print(c[i]) # 会调用__getitem__()方法
__iter__()
和__next__()
之所以把这两个放在一起,是因为我见到的这两个是在迭代器操作的时候同时出现的。直接看代码:class IterDemo: def __iter__(self): print('__iter__() is called') return NextDemo() # 需要返回一个实现了__next__()方法的类的对象 class NextDemo: def __next__(self): print('__next__() is called') iterDemo = IterDemo() nextDemo = iter(iterDemo) # 调用iterDemo.__iter__()方法 next(nextDemo) # 调用nextDemo.__next__()方法
__setattr__()
用在类内给成员变量赋值。class C: def __init__(self): self.a = 1 #调用一次__setattr__() def __setattr__(self, key, value): dict = self.__dict__ dict[key] = value print("__setattr__ !") def modify(self,new_a): self.a = new_a #调用一次__setattr__() c = C() c.modify(2)
输出:
__setattr__ ! __setattr__ !
参考:
Python下划线与命名规范python
_、
__和
__xx__的区别
pytorch学习笔记(四):输入流水线(input pipeline)
Python3关与迭代器next()使用为
__next__()的一点注意事项
相关文章推荐
- Python 类中方法的内部变量,命名加'self.'变成 self.xxx 和不加直接 xxx 的区别
- Python 3 与Python 2的区别
- for update 和for update of xxx的区别和用法
- Python3.x和Python2.x的区别
- Python3.1.2:wmain,main,_tmain的区别
- Python的ASCII, GB2312, Unicode , UTF-8区别
- Python里method和function的区别
- 垃圾题1-------------struts1和struts2区别------------来自XXX电子国企
- python:单引号,双引号和三引号的区别
- Python中Range和XRange的区别
- Python调用C的DLL和VC调用有什么区别?
- PHP和Python/Ruby运行机制的本质区别
- Python3.x和Python2.x的区别
- python 2.4与2.5中字符串与datetime转换的区别
- 表单提交到自身时action=”” 与action=”currentPage.xxx”的区别
- shell+sed+awk和perl和python的区别
- site:xxx.com和site:www.xxx.com的区别
- python中类属性和类实例的属性的区别
- Python3.1和Python2.5的区别
- Python的ASCII, GB2312, Unicode , UTF-8区别