python基金会主席入门教程_Python基金会(8),全栈,最全,学习,之路,基础,八

面向对象高级

一、常用内置函数

思考一:上节课掌握了类的定义和基本使用,可以通过点操作符去访问属性和方法,但是如果属性不存在会怎么办呢?

思考二:不希望因为属性不存在而出现报错,如何避免这个问题呢?

class Person:

def __init__(self,name,age,sex):

self.name = name

self.age = age

self.sex = sex

def run(self):

print(f'{self.name}今年{self.age}岁')

f7c4b7cb92724c5e06ca741ae7fe9d9c.png

hasattr判断属性是否存在

getattr得到属性值,没有则报错

setattr设置属性值

delattr删除属性

注意

:属性名需要加上引号,

attr是attribute

的缩写

上述这些就是类里面的内置函数,和我们一般在使用列表或者其他序列类型使用的添加删除转化等是一个道理。

属性的访问

if hasattr(xiaoyu,'name'):

a = getattr(xiaoyu,'name')

else:

setattr(xiaoyu,'name','xiangwang')

通过简单if判断就能避免属性不存在时,报错的问题,同时也可以设置属性值

a = getattr(xiaoyu,'name') if hasattr(xiaoyu,'name') else setattr(xiaoyu,'name','xiaowang')

思考:这个三目运算是否保证a得到属性值

是可以的

对象关系方法

class Person:

pass

class GuangDong(Person):

pass

class Hunxue(GuangDong):

pass

b0068e9a581ef550cd20edac129cd110.png

issubclass判断第一个类是不是后面类的子类

767262d9b04ac9d64170c353ba9a04ff.png

isinstance判断实例是否是后面类的实例

type也可以判断,但是只能判断单个类

总结

1、属性调用

掌握:hasattr、getattr、setattr、delattr

2、对象关系方法

掌握:isinstance和type方法

二、属性调用过程

思考一:学到现在已经接触了很多的内置方法,那么这么多方法,Python底层是如何去实现的呢?

属性调用过程

class Person:

def __init__(self,name,age,sex):

self.name = name

self.age = age

self.sex = sex

def run(self):

print(f'{self.name}今年{self.age}岁')

xiaoyu = Person('小宇',24,'男')

68760fe947a537b4002618684f0b94f7.png

这里调用了一些内置的方法,也会同样的效果

这是因为那些函数本身就是调用的这些方法

上述的例子我们看下如下这个

f6dd7f3a1614bff09d2462fdaef5735d.png

当我们在代码中加入如下代码

class Person:

def __init__(self,name,age,sex):

self.name = name

self.age = age

self.sex = sex

def run(self):

print(f'{self.name}今年{self.age}岁')

def __getattr__(self,item):

print('no attribute')

xiaoyu = Person('小宇',24,'男')

aeb61805f14f37daab358396af219ad1.png

当实例调用一个不存在的属性的时候,会发生报错,

但是如果增加__getattr__方法,则不会报错,而是执行此方法内的内容

属性调用过程

2f36beaa64c9db1afaf69481eead4b02.png

意思就是,当没有定义getattr的时候,系统他会自动调用__getattribute__这个隐藏的内置函数如判断有没有,有的话就返回,没得话就报错(这个是你没有自定义这个内置函数时候的功能),当你自定义以后,你要他输出什么他就输出什么切记自定义的函数名为__getattr__,如果你自定义的是__getattribute__这个函数那么你无论输入什么都是自己定义的输出

三、魔术方法

思考一:刚才展示了这些内置方法,通过这些可以看出,很多时候,都是在使用内置的方法来实现一些功能,通常把这些方法称之为魔法方法

class Earth:

def __new__(cls):

if not hasattr(cls,'_instance''):

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self):

self.name = 'earth'

Python中很多内置方法都是

两个下划线在两边

中间是单词名字

,并且这样的方法名字有一定的

特殊的含义

,把这种方法都称之为

魔法方法

比如这里的__new__方法,就是最开始调用的一个方法,会在初始化之前自动调用

单例模式

class Earth:

def __new__(cls):

if not hasattr(cls,'_instance'):

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self):

self.name = 'earth'

29c69386a037a32442813e097f275f58.png

利用__new__方法,可以很方便的去实现一个类的单例模式

单例模式的意思是:类始终只有

一个

实例存在,不会同时出现多个实例

输出魔法方法

根据上述代码我们如果要输出如下

9f6b6dc4a8cdb582efda37c23fcdc34f.png

如果我们想改变下输出的形式,这时候就需要改变他的底层执行方法了

class Earth:

def __new__(cls):

if not hasattr(cls,'_instance'):

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self):

self.name = 'earth'

def __str__(self):

return 'this is __str__ %s' % self.name

def __repr__(self):

return 'this is __repr__ %s' % self.name

0d517ebcc890f403e1f039264e919638.png

str

:修改

print

打印时的样子

repr

:修改直接打印时的样子

但是当我们只用一个呢

第一次我们注释掉__str__方法,试下

2a4a4b695586a13242642a26dc4fe72a.png

第二次我们注释掉__repr__方法,试下

fbd41573dd487123d6c58c69576269a0.png

对比下来还是有明显的差别的

总结

一下

1、在交互模式中,如果同时存在方法__str__和__repr__时候,直接打印的时候会调用第二个方法,print打印时候会调用第一个方法

2、在交互模式中,只存在__repr__方法时候,直接打印会调用这个方法,print打印时候会打印出__repr__方法里面的内容

3、在交互模式中,只存在__str__方法时候,直接诶打印会是一个函数体的那种形式,print打印时候会调用__str__方法里面的内容

四、协议

思考一:刚才已经自定义修改了很多属性,那再大胆点是否可以去自定义类似元组这样的序列类型呢?

class IndexTuple:

def __init__(self,*args):

self.values = tuple([x for x in args])

self.index = tuple(enumerate(self.values))

def __len__(self):

return len(self.values)

def __getitem__(self,key):

return self.index[key]

def __repr_(self):

return str(self.values)

a056fe903e9db530de2a4b63b08cbf5f.png

序列协议即定义:

len

getitem

setitem

、__delitem__等协议,如果不需要改变,那后两个就不要定义

Python中很多的协议,比如序列协议等很多协议,只要遵守这些协议,既可以说是对应的类型,比如定义了序列类型协议,则定义的类就是序列类型

迭代器协议

class Number:

def __init__(self,end=10):

self.start = 0

self.end = end

def __iter__(self):

return self

def __next__(self):

self.start += 1

if self.start >= self.end:

raise StopIteration

return self.start

nu = Number()

37cdb3362842f03e2f09aa262b960958.png

只要类实现了__iter__和__next__方法,则这个类就是迭代器,因此只要实现这两个方法,则是可以迭代对象

上下文协议

import time

class RunTime:

def __enter__(self):

self.start_time = time.time()

return self.start_time

def __exit__(self,exc_type,exc_val,exc_tb):

self.end_time = time.time()

self.run_time = self.end_time - self.start_time

print('Time consuming %s' % self.run_time)

a71b3df06a29d2a4f98af897e36da88c.png

同样的还有上下文协议,即我们之前讲过的with的使用,只是类里面定义__enter__和__exit__这两个方法,则可以使用with去使用此对象

五、本节课总结

1、常用内置函数

掌握:

hasattr、getattr、setattr、isinstance

2、属性调用过程

掌握:

属性调用的过程

3、魔法方法

掌握:

new

str

repr

4、协议

了解:

序列类型协议、上下文协议、迭代器协议

六、上节课作业

1、定义一个账户类,可以创建账户、存款、取款 、查询余额、以及销户等操作

2、现在三个人分别去开户,存款 和 销户,请利用上面的类实现出来

提示:账户必备要素:1、账户名 2、密码 3、余额

class Account:

def __init__(self,name,password,money=0):

self.name = name

self.pwd = password

self.money = money

def deposit(self,money):

pwd = input('请输入账户密码:')

if pwd == self.pwd:

if isinstance(money,(int,float)) and money >= 0:

self.money += money

return f'恭喜您存入金额{money}元,当前账户余额为{self.money}‘

else:

print('密码错误,请重新执行')

def balance(self,money):

pwd = input('请输入账户密码:')

if pwd == self.pwd:

if isinstance(money,(int,float)) and money >= 0 and money <= sefl.money:

self.money -= money

return f'你取了{money}元,当前账户余额为{self.money}‘

else:

print('密码错误,请重新执行')

def query(self,pwd):

if pwd == self.pwd:

return self.money

else:

print('密码错误,请重新执行')

mr = Acoount('moran','qwe123',10000)

def account_cancellation():

global mr

if mr.query('qwe123') == 0:

del mr

else:

print('当前账户还有余额请先取出')

f53552445ec7221ea384d1405e102f1d.png

七、作业

1、测试列表推导和不用列表推导哪一种速度耿凯

2、range不可以使用小数做步长,实现一个可迭代对象,可以实现小数步长

参考代码下期见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值