1:复习
class Person:
def __init__(self,local,name): #local,name属性名
self.local=local
self.name=name
def play(self): #类的方法
print(f'{self.name}的爱好')
na=Person('china','nana')
为什么要内置函数:
有些时候没有那些属性程序就会报错
对程序不太友好
2:判断实例对象是否存在:
hasattr()实例化对象,属性。
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
print(hasattr(na,'local'))
print(hasattr(na,'name'))
print(hasattr(na,'color'))
输出结果:
True
True
False
3:
getattr()实例对象,属性
输出对象属性
相当于实例对象点属性
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
print(na.local)
print(getattr(na,'local'))
输出结果:
china
china
4:
setattr()实例对象,属性,属性内容
增加属性或者修改属性
原本有那个属性就改,没有就增加
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
setattr(na,'age',18)
setattr(na,'name','haha')
print(na.age)
print(na.name)
5:
delattr()实例对象,属性
删除属性
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
delattr(na,'name')
print(hasattr(na.name))
直接报错,因为不存在
与三目运算的结合:
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
a=getattr(na,'age') if hasattr(na,'age') else setattr(na,'age',18)
print(a)
6:
issubclass()类,类
判断是否为子类:
判断后者是不是前者的子类:
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
class People(Person):
pass
print(issubclass(People,Person))
:
True
7:
isinstance()实例对象,类名
判断实例对象是否为类的实例
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
na=Person('china','nana')
class People(Person):
pass
print(isinstance(na,Person))
print(isinstance(na,People))
print(isinstance(na,(People,Person)))
True
False
True
8:
属性调用过程如果存在就可以打印出结果(添加print),
如果属性不存在就会报错,
只要我们修改报错那个部分,就可以实现不报错。
如下:
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
def play(self):
print(f'{self.name}的爱好')
def __getattribute__(self,item):#两个参数
print(item)#item就是自己输入的那个不存在的属性名
print('no attribute')
na=Person('china','nana')
print(na.age)
如果不修改就会报错了
9:魔术方法__new__
创建实例对象
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
#这个函数优先调用,
#表示重写,因此上面的init函数的实例化对象全都无效
def __new__(cls,*args,**kwargs):
print('这是new')
na=Person('china','nana')
print(getattu(na,'name'))
输出完
这是new
就会报错
将new方法继承父类
就可以使用了
class Person:
def __init__(self,local,name):
self.local=local
self.name=name
#这个函数优先调用
#表示重写,因此上面的init函数的实例化对象全都无效
def __new__(cls,*args,**kwargs):#cls就是这个类本身
print('这是new')
return super().__new__(cls) #返回变量
na=Person('china','nana')
print(na.name)
10:单例模式
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
return super().__new__(cls)
na=Person('china')
oo=Person('china')
我们发现na,oo的属性名是一样的
如何只能让一个存在(地址)呢?
对new方法进行修改
如下:
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
#*args,**kwargs分别是列表不定长,元组不定长
if not hasattr(cls,'_istance'):#istance是习惯用法,就是一个变量
#这里判断是否存在,不存在就把实例对象赋值给_istance
cls._istance=super().__new__(cls)
return cls._istance
#_instance肯定是不存在的所以自动执行下一行把实例对象赋值给
#cls_istance,同时他就存在了,然后返回。
#因此na,oo的地址就一致了
na=Person('china')
oo=Person('哈哈')
11:输出魔法方法:
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_istance'):
cls._istance=super().__new__(cls)
return cls._istance
oo=Person('哈哈')
print(oo)
看不懂!!
<__main__.Person object at 0x00000168053F67F0>
为了让我们读懂:
就有了输出方法:如下
方法一:str
在交互模式也要输入print
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_istance'):
cls._istance=super().__new__(cls)
return cls._istance
def __str__(self):
return 'this is __str__%s' %self.local
oo=Person('哈哈')
print(oo)
这样子咱们就能读懂了
this is __str__哈哈
方法二:repr
在交互模式下不用输入print,可以直接打印
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_istance'):
cls._istance=super().__new__(cls)
return cls._istance
#def __str__(self):
# return 'this is __str__%s' %self.local
def __repr__(self):
return 'this is __repr__%s' %self.local
oo=Person('哈哈')
print(oo)
两种方法如果同时都有:默认先调用str方法
12:call
把实例对象变为可调用的方法
class Person:
def __init__(self,local):
self.local=local
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_istance'):
cls._istance=super().__new__(cls)
return cls._istance
#def __str__(self):
# return 'this is __str__%s' %self.local
def __repr__(self):
return 'this is __repr__%s' %self.local
def __call__(self):
print('用实例对象做方法')
oo=Person('哈哈')
print(oo)
oo()
this is __repr__哈哈
用实例对象做方法
协议:两个或者两个以上的魔术方法才能实现的效果
13:序列协议:下标取值
class Person:
def __init__(self,*args):#元组不定长,之后就不用一个往里输了
self.values=[x for x in args]#保存元组里单位值
self.index=list(enumerate(self.values))#通过枚举获得索引
#打印出来的就是下标,值
def __getitem__(self,key):
return self.index[key]
lee=Person(2,5,6)
print(lee[2])
14:迭代协议:iter,next
#类想要迭代必须添加迭代协议
class Number():
def __init__(self,end=10):
self.start=0
self.end=end#迭代十次
def __iter__(self):#让类变成可迭代对象
return self
def __next__(self):#迭代器f=li.__iter__()
self.start += 1
if self.start>=self.end:
#主动报错 raise抛出异常
raise StopIteration
return self.start
nu=Number()
#调用next(nu)就可以迭代了
15:上下文协议:
import time
#让类有上下文协议,就可以使用with调用类
class Rutime:
def __enter__(self):
self.start=time.time()
return self.start
def __exit__(self,exc_type,exc_val,exc_tb):#异常的类型异常的值异常的信息
self.end=time.time()
self.run=self.end-self.start#运行时间
print('时间运行:%s'%self.run)
with Rutime():
for i in range(1000000):
pass