__getitem__,__getattr__
__getattr__内置使用点号获取实例属性属性如 s.name,自调用__getattr__ __setattr__设置类实例属性 如s.name='tom',自调用__setattr__ __getitem__ 使用[]获取实例属性 如s['name'],自调用__getitem__ __setitem__ 使用[]设置实例属性如 s['name'] = 'tom' ,自调用__setitem__ __dict__ 为参数字典 如下代码: class Student: def __getattr__(self, item): return item + ' is not exits' def __setattr__(self, key, value): self.__dict__[key] = value def __getitem__(self, item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key] = value s = Student() print(s.name) # 调用__getattr__方法 输出'name is not exits' s.age = 1 # 调用__setattr__ 方法 print(s.age) # 输出 1 print(s['age']) # 调用 __getitem__方法 输出1 s['name'] = 'tom' # 调用 __setitem__ 方法 print(s['name']) # 调用 __getitem__ 方法 输出 'tom'
把模块当做脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
1 def hasattr(*args, **kwargs): # real signature unknown 2 """ 3 Return whether the object has an attribute with the given name. 4 5 This is done by calling getattr(obj, name) and catching AttributeError. 6 """ 7 pass
1 def getattr(object, name, default=None): # known special case of getattr 2 """ 3 getattr(object, name[, default]) -> value 4 5 Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. 6 When a default argument is given, it is returned when the attribute doesn't 7 exist; without it, an exception is raised in that case. 8 """ 9 pass
1 def setattr(x, y, v): # real signature unknown; restored from __doc__ 2 """ 3 Sets the named attribute on the given object to the specified value. 4 5 setattr(x, 'y', v) is equivalent to ``x.y = v'' 6 """ 7 pass
1 def delattr(x, y): # real signature unknown; restored from __doc__ 2 """ 3 Deletes the named attribute from the given object. 4 5 delattr(x, 'y') is equivalent to ``del x.y'' 6 """ 7 pass
1 class Foo: 2 f = '类的静态变量' 3 def __init__(self,name,age): 4 self.name=name 5 self.age=age 6 7 def say_hi(self): 8 print('hi,%s'%self.name) 9 10 obj=Foo('egon',73) 11 12 #检测是否含有某属性 13 print(hasattr(obj,'name')) 14 print(hasattr(obj,'say_hi')) 15 16 #获取属性 17 n=getattr(obj,'name') 18 print(n) 19 func=getattr(obj,'say_hi') 20 func() 21 22 print(getattr(obj,'aaaaaaaa','不存在啊')) #报错 23 24 #设置属性 25 setattr(obj,'sb',True) 26 setattr(obj,'show_name',lambda self:self.name+'sb') 27 print(obj.__dict__) 28 print(obj.show_name(obj)) 29 30 #删除属性 31 delattr(obj,'age') 32 delattr(obj,'show_name') 33 delattr(obj,'show_name111')#不存在,则报错 34 35 print(obj.__dict__)
1 class Foo(object): 2 3 staticField = "old boy" 4 5 def __init__(self): 6 self.name = 'wupeiqi' 7 8 def func(self): 9 return 'func' 10 11 @staticmethod 12 def bar(): 13 return 'bar' 14 15 print getattr(Foo, 'staticField') 16 print getattr(Foo, 'func') 17 print getattr(Foo, 'bar')
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import sys 5 6 7 def s1(): 8 print 's1' 9 10 11 def s2(): 12 print 's2' 13 14 15 this_module = sys.modules[__name__] 16 17 hasattr(this_module, 's1') 18 getattr(this_module, 's2')
导入其他模块,利用反射查找该模块是否存在某个方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 def test(): 5 print('from the test')
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 """ 5 程序目录: 6 module_test.py 7 index.py 8 9 当前文件: 10 index.py 11 """ 12 13 import module_test as obj 14 15 #obj.test() 16 17 print(hasattr(obj,'test')) 18 19 getattr(obj,'test')()
__str__和__repr__
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
1 #_*_coding:utf-8_*_ 2 3 format_dict={ 4 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 5 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 6 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 7 } 8 class School: 9 def __init__(self,name,addr,type): 10 self.name=name 11 self.addr=addr 12 self.type=type 13 14 def __repr__(self): 15 return 'School(%s,%s)' %(self.name,self.addr) 16 def __str__(self): 17 return '(%s,%s)' %(self.name,self.addr) 18 19 def __format__(self, format_spec): 20 # if format_spec 21 if not format_spec or format_spec not in format_dict: 22 format_spec='nat' 23 fmt=format_dict[format_spec] 24 return fmt.format(obj=self) 25 26 s1=School('oldboy1','北京','私立') 27 print('from repr: ',repr(s1)) 28 print('from str: ',str(s1)) 29 print(s1) 30 31 ''' 32 str函数或者print函数--->obj.__str__() 33 repr或者交互式解释器--->obj.__repr__() 34 如果__str__没有被定义,那么就会使用__repr__来代替输出 35 注意:这俩方法的返回值必须是字符串,否则抛出异常 36 ''' 37 print(format(s1,'nat')) 38 print(format(s1,'tna')) 39 print(format(s1,'tan')) 40 print(format(s1,'asfdasdffd'))
1 class B: 2 3 def __str__(self): 4 return 'str : class B' 5 6 def __repr__(self): 7 return 'repr : class B' 8 9 10 b=B() 11 print('%s'%b) 12 print('%r'%b)
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
1 class Foo: 2 3 def __del__(self): 4 print('执行我啦') 5 6 f1=Foo() 7 del f1 8 print('------->') 9 10 #输出结果 11 执行我啦 12 ------->
item系列
__getitem__\__setitem__\__delitem_
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
__new__
1 class A: 2 def __init__(self): 3 self.x = 1 4 print('in init function') 5 def __new__(cls, *args, **kwargs): 6 print('in new function') 7 return object.__new__(A, *args, **kwargs) 8 9 a = A() 10 print(a.x)
1 class Singleton: 2 def __new__(cls, *args, **kw): 3 if not hasattr(cls, '_instance'): 4 cls._instance = object.__new__(cls, *args, **kw) 5 return cls._instance 6 7 one = Singleton() 8 two = Singleton() 9 10 two.a = 3 11 print(one.a) 12 # 3 13 # one和two完全相同,可以用id(), ==, is检测 14 print(id(one)) 15 # 29097904 16 print(id(two)) 17 # 29097904 18 print(one == two) 19 # True 20 print(one is two)
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
1 class Foo: 2 3 def __init__(self): 4 pass 5 6 def __call__(self, *args, **kwargs): 7 8 print('__call__') 9 10 11 obj = Foo() # 执行 __init__ 12 obj() # 执行 __call__
__len__
1 class A: 2 def __init__(self): 3 self.a = 1 4 self.b = 2 5 6 def __len__(self): 7 return len(self.__dict__) 8 a = A() 9 print(len(a))
__hash__
1 class A: 2 def __init__(self): 3 self.a = 1 4 self.b = 2 5 6 def __hash__(self): 7 return hash(str(self.a)+str(self.b)) 8 a = A() 9 print(hash(a))
__eq__
1 class A: 2 def __init__(self): 3 self.a = 1 4 self.b = 2 5 6 def __eq__(self,obj): 7 if self.a == obj.a and self.b == obj.b: 8 return True 9 a = A() 10 b = A() 11 print(a == b)
1 class FranchDeck: 2 ranks = [str(n) for n in range(2,11)] + list('JQKA') 3 suits = ['红心','方板','梅花','黑桃'] 4 5 def __init__(self): 6 self._cards = [Card(rank,suit) for rank in FranchDeck.ranks 7 for suit in FranchDeck.suits] 8 9 def __len__(self): 10 return len(self._cards) 11 12 def __getitem__(self, item): 13 return self._cards[item] 14 15 deck = FranchDeck() 16 print(deck[0]) 17 from random import choice 18 print(choice(deck)) 19 print(choice(deck))
1 class FranchDeck: 2 ranks = [str(n) for n in range(2,11)] + list('JQKA') 3 suits = ['红心','方板','梅花','黑桃'] 4 5 def __init__(self): 6 self._cards = [Card(rank,suit) for rank in FranchDeck.ranks 7 for suit in FranchDeck.suits] 8 9 def __len__(self): 10 return len(self._cards) 11 12 def __getitem__(self, item): 13 return self._cards[item] 14 15 def __setitem__(self, key, value): 16 self._cards[key] = value 17 18 deck = FranchDeck() 19 print(deck[0]) 20 from random import choice 21 print(choice(deck)) 22 print(choice(deck)) 23 24 from random import shuffle 25 shuffle(deck) 26 print(deck[:5])
1 class Person: 2 def __init__(self,name,age,sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 7 def __hash__(self): 8 return hash(self.name+self.sex) 9 10 def __eq__(self, other): 11 if self.name == other.name and self.sex == other.sex:return True 12 13 14 p_lst = [] 15 for i in range(84): 16 p_lst.append(Person('egon',i,'male')) 17 18 print(p_lst) 19 print(set(p_lst))