python中的特殊变量
- 类似__xx,以双下划线开头的实例变量名,是一个私有变量(private),只有内部可以访问,外部不能访问;
- 类似__xx__,以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,它不是private变量,下面会介绍Python中的常见特殊变量;
- 类似_x,以单下划线开头的实例变量名,这样的变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是请把我视为私有变量,不要随意访问”。
特殊变量
#__name__
- 如果直接执行某个
.py
文件的时候,这个文件里面的__name__
就是__main__
,如果不是直接执行,而是被另外一个.py
文件import
的时候,这个文件里面的__name__
是这个py
的文件名。 - 使用这个
__name__
可以对程序进行调试,如果说当程序之间互相之间调用,比较复杂的关系的时候,使用if __name__ == '__main__':
将执行的代码放在里面,在执行其他的程序的时候,测试的程序本身不会运行,而这个程序有问题的时候,可以执行这个文件,那么if __name__ == '__main__':
里面的代码就执行了。
#__doc__
获取模块注释
#__file__
当前执行文件的路径
#__cached__
对应pycache文件的位置
#__name__
执行当前文件的时候,等于__main__;否则不等于;一般在主文件里写
#__package__
模块所在package
#__all__
python模块中的__all__,可用于模块导入时限制,如:
from module import *
此时被导入模块若定义了__all__属性,则只有__all__内指定的属性、方法、类可被导入。
若没定义,则导入模块内的所有公有属性,方法和类 。
# 在别的模块中,导入该模块时,只能导入__all__中的变量,方法和类 __all__ = ('A', 'func') class A(): def __init__(self, name, age): self.name = name self.age = age class B(): def __init__(self, name, id): self.name = name self.id = id def func(): print('func() is called!') def func1(): print('func1() is called!')
#test.py中定义了__all__属性,只能导入__all__中定义的属性,方法和类 from test import * a=A('python','24') print(a.name,a.age) func() #func1() #NameError: name 'func1' is not defined #b=B('python',123456) #NameError: name 'B' is not defined
#__slots__
Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性范围
class P(object): __slots__ = ("name", "age") pass
#__init__()
构造函数,创建实例的时候,可以调用__init__方法做一些初始化的工作,如果子类重写了__init__,实例化子类时,则只会调用子类的__init__,此时如果想使用父类的__init__,可以使用super函数,如下:
class P(object): def __init__(self, name, score): self.name = name self.score = name class C(P): def __init__(self, name, score, age): super(C, self).__init__(name, score) self.age = age
#__new__()
注意:__init__是实例创建之后调用的第一个方法,而__new__更像构造函数,它在__init__之前被调用。
另外,__new__方法是一个静态方法,第一参数是cls,__new__方法必须返回创建出来的实例。
例如,用__new__实现单例模式:
class Singleton(object): def __new__(cls): # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象 if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() obj1.attr1 = 'value1' print(obj1.attr1, obj2.attr1) print(obj1 is obj2)
#__del__()
析构函数:__del__() 释放对象是自动调用
#__str__()
在调用print打印对象时自动调用,是给用户用的,是一个描述对象的方法。
#__repr__()
是给机器用的,在Python解释器里面直接敲对象名在回车后调用的方法。(用于调试)
# test.py class P(object): def __str__(self): return "__str__ called" def __repr__(self): return "__repr__ called" p = P()
可以看下__str__和__repr__的区别:
>>> from test import p >>> p __repr__ called >>> print p __str__ called
#__enter__
#__exit__
这两个方法是用于支持with语句的上下文管理器。
例如让文件句柄支持with语法的实现:
class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): return self.file_obj def __exit__(self, type, value, traceback): self.file_obj.close() with File('demo.txt', 'w') as opened_file: opened_file.write('Hola!')
#__iter__
next
如果一个类想被用于for ... in
循环,类似list或tuple那样,就必须实现一个__iter__()
方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()
方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self): return self # 实例本身就是迭代对象,故返回自己 def next(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration(); return self.a # 返回下一个值
#__call__
实例可以像函数一样调用。
class Student(object): def __init__(self): self.name = "Michael" def __call__(self): print('__call__ called') s = Student() s()
#__getitem__
#__setitem__
#__delitem__
支持下标(或切片)操作的函数
class Fib(object): def __getitem__(self, n): if isinstance(n, int): a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): start = n.start stop = n.stop a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L fib = Fib() print(fib[10]) print(fib[0:10])
#__getattr__
#__getattribute__
#__setattr__
#__delattr__
支持点操作(即 "对象.属性" 访问方式),
当访问不存在的属性时,才会使用__getattr__ 方法。
class Student(object): def __init__(self): self.name = "Michael" def __getattr__(self, attr): print '__getattr__ called' if attr=='score': return 99 elif attr=='name': return "Tom" s = Student() print(s.score) # 99 print(s.name) # Michael
Python的字典支持下标操作,但不支持 "." 操作,如果想让其支持,如下实现:
class Storage(dict): __slots__ = () """ A Storage object is like a dictionary except `obj.foo` can be used in addition to `obj['foo']`. >>> o = Storage(a=1) >>> o.a >>> o['a'] >>> o.a = 2 >>> o['a'] >>> del o.a >>> o.a Traceback (most recent call last): ... AttributeError: 'a' >>> 'b' in o False """ def __getattr__(self, key): try: return self[key] except KeyError, k: raise AttributeError(k) def __setattr__(self, key, value): self[key] = value def __delattr__(self, key): try: del self[key] except KeyError, k: raise AttributeError(k) def __repr__(self): return '<Storage ' + dict.__repr__(self) + '>'