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)
反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
class A: def func(self): print('in func') a = A() a.name = 'alex' a.age = 63 ret = getattr(a,'name') #通过变量名的字符串形式取到的值 sss = input('>>>') print(getattr(a,sss))
class A: def func(self): print('in func') a = A() a.name = 'alex' a.age = 63 #反射对象的方法 ret = getattr(a,'func') ret()
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #检测是否含有某属性 print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #获取属性 n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','不存在啊')) #报错 #设置属性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #删除属性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,则报错 print(obj.__dict__)
#导入当前模块 import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2') #导入模块也可以反射 def test(): print('from the test') """ 程序目录: module_test.py index.py 当前文件: index.py """ import module_test as obj #obj.test() print(hasattr(obj,'test')) getattr(obj,'test')()
__str__和__repr__
内置的类方法和内置的函数之间有千丝万缕的联系
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
class A: def __str__(self): return "A's object" a = A() print(a) #a.__str__ #打印一个对象的时候,就是调用a.__str__ ''' object里有一个__str__,一旦被调用,就返回调用这个方法的对象地址 %s str() 直接打印 实际上都是走的__str__ %r repr() 实际上都是走的__repr__ repr 是str的备胎,但str不能做repr的备胎 srt(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法 有,那么他返回的必定是一个str类型,如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__ repr(),只会找__repr__,如果没有找父类的 '''
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b=B() print('%s'%b) print('%r'%b) ''' str函数或者print函数--->obj.__str__() repr或者交互式解释器--->obj.__repr__() 如果__str__没有被定义,那么就会使用__repr__来代替输出 注意:这俩方法的返回值必须是字符串,否则抛出异常 '''
__del__
class Foo: def __del__(self): print('执行我啦') f1=Foo() del f1 print('------->')
析构方法,当对象在内存中被释放时,自动触发执行,先执行后删除。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
__len__
内置的方法有很多 不一定全都在object中 class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a)) class B: def __len__(self): return 10 b= B() print(len(b))
__call__
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
item系列
class Foo: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __getitem__(self,item): if hasattr(self,item): return self.__dict__[item] def __setitem__(self,key,value) : self.__dict__[key] = value def __delitem__(self,key): del self.__dict__[key] f = Foo('zack',38,'男') print(f['name']) f['hobby'] = '男' print(f.hobby,f['hobby']) del f.hobby #object 原生支持 __delattr__ del f['hobby'] #通过自己实现的 print(f.__dict__)
__new__
#init是初始化方法,__new__是构造方法:创建一个对象 class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls,*args,**kwargs): print('in new function') return object.__new__(A,*args,**kwargs) a = A() print(a,x)
''' 设计模式 单例模式:一个类始终只有一个实例 当你第一次实例化这个类的时候 就创建一个实例化的对象 当你之后再来实例化的时候 就用之前的创建的对象 ''' class A: __instance = False def __init__(self,name,age): self.name = name self.age = age def __new__(cls,*args,**kwargs) if cls.__instance: return cls.__instance cls.__instance = object.__new__(A) return cls.__instance e = A('egg',38) z = A('zack',25) print(egg) print(zack)
__eq__
class A: def __init__(self,name): self.name = name def __eq__(self,other): if self.__dict__ == other.__dict__: return True else: return False obj1 = A('egg') obj2 = A('egg') print(obj1 == obj2)
__hash__
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5])
''' 有一个类的init方法如下: class Person: def __init__(self,name,age,sex,weight): self.name = name self.sex = sex self.age = age self.weight = weight 假设有100个person的对象, 若两个对象的obj1,obj2的name和sex属性相同 即obj1.name==obj2.name and obj1.sex==obj2.sex 我们认为两个对象为同一个对象,已知一个列表中的100个对象,对这100个对象进行去重。 提示: 重写Person类重的两个内置方法 ''' class Person: def __init__(self,name,age,sex,weight): self.name = name self.sex = sex self.age = age self.weight = weight def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True return False def __hash__(self): return hash(self.name+self.sex) person = Person('sole',20,'男',80) person1 = Person('sole',21,'男',80) print(set((person,person1)))