Python-面向对象进阶
isinstance和issubclass
isinstance() :判断一个对象是不是这个类的实例,如果这个类有父类,那么这个对象也是其父类的对象
issubclass() : 判断两个类是不是父子关系,接受两个参数(子类,父类)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo:
pass
s=Foo()
print(isinstance(s,Foo)) #True
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
print(issubclass(Bar, Foo)) #True
反射
反射: 把一个字符串数据类型的变量变成一个真实存在在这个程序中的变量名,并且能够使用它
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
#-对象中的反射
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(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73}
print(hasattr(obj,'name')) #True
print(hasattr(obj,'say_hi')) #True
print(hasattr(obj,'aaa')) #False
#获取属性
n=getattr(obj,'name') # = obj.name
print(n) # egon
n= obj.name
print(n) # egon
func=getattr(obj,'say_hi')
print(func) # <bound method Foo.say_hi of <__main__.Foo object at 0x0000000001E805F8>>
func() # hi,egon
func=getattr(obj,'aaa','bbb')
print(func) # bbb
#设置属性
setattr(obj,'sb',True) #obj.sb=True
print(obj.sb) #True
print(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73, 'sb': True}
setattr(obj,'show_name',lambda self:self.name+'sb') # obj.show_name()
print(obj.show_name(obj)) # egonsb
print(obj.__dict__) # {'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x0000000001D13E18>}
#删除属性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,则报错
#-类中的反射
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(Foo.__dict__) #{'__module__': '__main__', 'f': '类的静态变量', '__init__': <function Foo.__init__ at 0x00000000029D5BF8>,
# 'say_hi': <function Foo.say_hi at 0x00000000029D5C80>, '__dict__': <attribute '__dict__' of 'Foo' objects>,
# '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
print(hasattr(Foo,'f')) # True
print(getattr(Foo,'say_hi')) # <function Foo.say_hi at 0x00000000029D5C80>
getattr(Foo,'say_hi')() #会报错 如果传个实例化对象就不会
getattr(Foo,'say_hi')(obj) # hi,egon
setattr(Foo,'a','abc') # Foo.a='abc'
print(Foo.__dict__) # 最后多了一个 'a': 'abc'
print(Foo.a) # abc
delattr(Foo,'a')
delattr(Foo,'say_hi')
delattr(Foo,'f')
print(Foo.__dict__) # {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000029E5BF8>,
# '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
#-类中的反射与类方法,静态方法结合使用
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
@classmethod
def func(cls):
return cls.staticField
@classmethod
def func1(cls,a):
return a+cls.staticField
@staticmethod
def bar():
return 'bar'
a='a'
print(Foo.staticField) # old boy
print(getattr(Foo, 'staticField')) # old boy
print(getattr(Foo, 'bar')()) # bar 调用静态方法
print(getattr(Foo, 'func')()) # old boy 调用类中方法
print(getattr(Foo, 'func1')(a)) # aold boy 调用类方法,并往其中传参
#-当前模块的反射 import sys def s1(): print ('s1') def s2(): print ('s2') xiaoxuanxuan = 2222 this_module = sys.modules[__name__] # 在自己文件中__name__会变成__main__ 自身文件的模块名 用模块名.属性或方法查看 print(getattr(this_module, 'xiaoxuanxuan')) #22222 print(hasattr(this_module, 's1')) # True getattr(this_module, 's2')() # s2
#导入其他模块,利用反射查找该模块是否存在某个方法
# module_test.py与index.py在同一目录下
# 在module_test.py中
def test():
print('from the test')
# 在index.py中
import module_test as obj
print(hasattr(obj,'test')) # True
getattr(obj,'test')() # from the test
__str__和__repr__
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type
def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
# def __str__(self):
# return '(%s,%s)' %(self.name,self.addr)
s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1)) # from repr: School(oldboy1,北京)
print('from str: ',str(s1)) # from repr: School(oldboy1,北京)
print(s1) # School(oldboy1,北京)
class B:
def __str__(self):
return 'str : class B'
def __repr__(self):
return 'repr : class B'
b=B()
print('%s'%b) # str : class B
print('%r'%b) # repr : class B
class Animal:
def __init__(self,kind,name):
self.kind = kind
self.name = name
def __str__(self):
return 'str : %s : %s'%(self.kind,self.name)
def __repr__(self):
return 'repr : %s : %s'%(self.kind,self.name)
cat = Animal('cat','guolei')
print('%s'%cat) # str : cat : guolei
print('%r'%cat) # repr : cat : guolei
print(str(cat)) # str : cat : guolei
print(repr(cat)) # repr : cat : guolei
format_dict={
'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type
def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
def __str__(self):
return '(%s,%s)' %(self.name,self.addr)
def __format__(self, format_spec):
# if format_spec
if not format_spec or format_spec not in format_dict:
format_spec='nat'
fmt=format_dict[format_spec]
# obj=self
return fmt.format(obj=self)
s1=School('oldboy1','北京','私立')
print(format(s1,'nat')) # oldboy1-北京-私立
__del__
析构方法,当对象在内存中被释放时,自动触发执行。 或者使用 del 对象 自动触发类中__del__
class Foo:
def __del__(self):
print('执行我啦')
f1=Foo()
del f1
print('------->')
#输出结果
执行我啦
------->
class A:
def __del__(self):
print('aaa')
class B:
def __del__(self):
print('bbb')
a=A()
b = B()
print('ccc')
#输出
ccc
aaa
bbb
item系列
__getitem__\__setitem__\__delitem__
class Animal:
def __init__(self,name):
self.name = name
def __getitem__(self, item):
return getattr(self,item)
def __setitem__(self, key, value):
setattr(self,key,value)
def __delitem__(self, key):
delattr(self,key)
cat = Animal('guolei')
print(cat['name']) #去类中找getitem方法 guolei
cat['sex'] = '公' #去类中找setitem方法
print(cat.sex) #公
print(cat['sex']) #公
print(cat.__dict__) #{'name': 'guolei', 'sex': '公'}
del cat['name'] # 去类中找delattr方法
print(cat.__dict__) #{'sex': '公'}
__new__
单例模式 实例始终只有一个 他的属性可以随着你的改变而改变
#正常情况下,示例化后先进行__new__方法,在父类object方法中new出一个新对象,给予__init__方法中的self,这就是正常情况下实例化对象的步骤
#即先去元祖那里,创建一个人(裸体的人),再为这个人穿衣服(在__init__方法中的self实例化)
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)
#输出:
in new function
in init function
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
__len__
对于 __len__ 方法的执行是由len(对象)后触发的,即:len(对象)
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a)) # 2
print(a.__dict__) # {'a': 1, 'b': 2}
__hash__
对于 __hash__ 方法的执行是由hash(对象)后触发的,即: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)) # -7422275419112235454 每次运行都不相同
__eq__
对于 __eq__ 方法的执行是由 对象 == 对象 后触发的,即:对象 == 对象
class A:
def __init__(self):
self.a = 1
self.b = 2
def __eq__(self,obj): # ==前面是对象,==后面是变量
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b) # True
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])
from collections import namedtuple
Card = namedtuple('Card',['rank','suit'])
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]) # 第一张 Card(rank='2', suit='红心')
from random import choice
print(choice(deck)) #随机抽一张 Card(rank='2', suit='黑桃')
print(choice(deck)) #随机抽一张 Card(rank='A', suit='梅花')
from random import shuffle
shuffle(deck)
print(deck[:5]) # 抽五张
纸牌游戏
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:return True
p_lst = []
for i in range(84):
p_lst.append(Person('egon',i,'male'))
print(p_lst) # 一百个对象的列表
print(set(p_lst)) # 只有一个对象,set()方法运行了类中的__hash__与__eq__方法
面试题,一百个对象中去重


浙公网安备 33010602011771号