目录python
封装: 就是打包,封起来,装起来,把你丢进袋子里,而后用绳子把袋子绑紧,你还能拿到袋子里的那我的吗?函数
1.隐藏属性和方法,外部(类的外部)没法使用,内部(类额内部)可使用,在类定义阶段就执行了,真的想引用,就使用_类名__属性名学习
封装分为两个层面:优化
第一个层面: 对象能拿到类的东西,可是类能拿到对象的东西吗?编码
class Foo(): count = 0 print(count) f = Foo() print(f.count) f.name = 'nick' # 对 对象进行了封装,类拿不到对象的name print(Foo.name) # AttributeError: type object 'Foo' has no attribute 'name'
AttributeError
英文:属性错误的意思code
第二个层面的: 内部(类的内部)可使用,外部(类的外部)不可使用,在你须要封装的属性前面加上__对象
# 之前定义变量并不会如下划线开头,如下划线开头的变量,好比隐藏属性,或者如下划线开头方法,在某种状况下会自动调用,好比__init__() lass People(): lover = 'male' print('in',lover) # 内部可用lover print('out',People.lover) # 外部可用lover # 属性隐藏,在属性前加__ class People(): __lover = 'male' print('in',__lover) # 内部可用__lover # print('out',People.__lover) # 外部不能够用__lover print('out',People._People__lover) # out male 若是你真的要拿,_类名__属性去拿(不可能这样作) # 函数隐藏,在函数前加__函数名 # 正常 class People(): def eat(self): print('eat') People.eat(111) # 类调用,须要传参 pe = People() pe.eat() # 隐藏方法 class People(): __love_people = 'male' # print('in',love_people) 报错 # print('in',__love_people) 报错 # 定义一个吃饭的流程:拿碗,拿筷子,吃饭 def __nawan(self): print('nawan') def __nakuaizi(self): print('nakuaizi') def __chifan(self): print('chifan') def chifan_all(self): # 吃饭 self.__nawan() self.__nakuaizi() self.__chifan() # print('out',People.__nawan(11)) # 报错,不能够引用内部的__nawan函数,函数进行了隐藏 p = People() # print('out',p.nawan()) # print('out',p.nakuaizi()) # print('out',p.chifan()) print('out',p.chifan_all())
2.隐藏模块内的函数/变量 _x: from module import * (没法导入),from module import _x(不合理)it
# 正常状况下 # m1.py x= 10 def f1(): print('from f1') # m2.py from m1 import x # from m1 import * print(x) f1() #如今对模块内的函数/变量 进行隐藏 # m1.py _x= 10 def __f1(): print('from f1') # m2.py from m1 import _X,__f1 (能够导入_x,__f1,可是不合理,变量/函数前面加_或者__都行,主要原模块m1中变量或者函数名写成什么样,m2单独导入就导什么样) # from m1 import * (导不出_x,__f1) ,除掉注释,下面两行代码都会报错 print(_x) # 能够导入 __f1() # 能够导入
对属性这个封装有什么用:藏起来了,保护了你的隐私,类内部的属性不想让其余人访问io
对方法封装有什么好处:精简了代码,你吃饭就使用chifan_all这个方法就能够了,不须要去关心其余的操做,而且外部调用者也不知道你内部发生了什么function
作一个小练习,理解封装其实在定义阶段就已经执行了,会把私有属性__f1变成 _Foo__f1,以后都不会作这种处理
class Foo: def __f1(self): print('Foo.f1') def f2(self): print('_Foo__f1') self.__f1() print(Foo.__dict__) #注意字典中 __f1 变成了什么,_Foo__f1 {'__module__': '__main__', '_Foo__f1': <function Foo.__f1 at 0x00000231DCBE0488>, 'f2': <function Foo.f2 at 0x00000231DCBE0510>, '__dict__': <attr class Bar(Foo): def __f1(self): print('Bar.f1') bar = Bar() # 实例化一个对象 bar.f2() # 对象bar中找f2,没有,而后Bar类也没有,去父类Foo找,找到f2,打印 _Foo__f1,再执行self.__f1(),self是对象,对象有__f1,打印 Bar.f1 bar.f2() # _Foo__f1,Bar.f1
class Foo(): __count = 0 foo = Foo() print(foo) foo.__y = 1 # 给对象foo添加属性__y print(foo.__y) # 1
@property : 被@property 装饰的函数会从函数变成属性,也就是说直接 .函数名,不须要加括号使用
# BMI class People(): def __init__(self,height,weight): self.height = height self.weight = weight @property def bmi(self): return self.weight/(self.height**2) peo = People(1.8,70) print(peo.height) # print(peo.bmi()) 没用 @property的时候须要这样写 print(peo.bmi)
@方法名.setter : 被@方法名.setter 装饰的函数,方法名修改,会执行这个装饰的函数
@方法名.deleter: 被@方法名.deleter 装饰的函数,方法名删除,会执行这个装饰的函数
# 装饰器用法(只在Python3中使用) class People(): def __init__(self,height,weight): self.height = height self.weight = weight @property # 获取值的时候触发,你不须要加括号使用,不能加参数 def bmi(self): return self.weight/(self.height**2) @bmi.setter # 在修改bmi的时候触发,必须得加参数 def bmi(self, value): print(f'你已经成功修改成{value}') @bmi.deleter # 在删除bmi的时候触发,不能加参数 def bmi(self): print('delter') peo = People(1.8,70) print(peo.bmi) print('*'*50) peo.bmi = 50 print('*'*50) del peo.bmi
绑定方法: 绑定的方法
1.对象的绑定方法:没有加任何装饰的方法就是对象的绑定方法
2.类的绑定方法: 加了@classmethod装饰器的方法就是类的绑定方法
3.非绑定方法: 加了@staticmethod装饰器的方法就是非绑定方法,其实就是一个普通的函数
@property 让函数方法 bmi() 变成属性,
@bmi.setter 和 @bmi.deleter 让这个函数方法 bmi() 能够进行属性同样的修改和删除,
因此 @bmi.setter 和 @bmi.deleter 装饰的函数方法名必须是property装饰的函数方法名bmi(),而不能够是随意定义的函数名字,若是换成其余名字会报错,显示的就是该属性(实际是个函数)没法进行修改或删除。
随意定义函数方法名是 类属性方法使用property 能够拥有的
class Foo: # 绑定给对象,只有对象能用,可是类也能使用,使用的时候必须得传参 def f1(self): print(self) @classmethod # 让被装饰的函数给类使用,约定俗称参数为cls # 绑定给类的方法,类能使用,对象也可使用,可是参数依然是类 def f2(cls): print(cls) # 什么都不绑定的,非绑定方法,定义了普通的函数 @staticmethod def f3(self): print(self) f = Foo() f.f1() Foo.f1(1111) print('*' * 50) Foo.f2() f.f2() print('*'*50) Foo.f3(2222) f.f3(2222) # f为对象,但f3为普通函数,该传什么参就传什么参
<__main__.Foo object at 0x000002C80DCBC828> 1111 ************************************************** <class '__main__.Foo'> <class '__main__.Foo'> ************************************************** 2222 2222
🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸
学习python已有月把时间,强烈推荐小伙伴们要开始培养本身优化代码的思惟了
《编写高质量代码:改善python程序的91个建议》
《编写高质量python代码的59个有效方法》--》改善代码的风格
《流畅的python》--》面向对象
以上三本书看不懂的跳过,是潜移默化去熏陶编码的思惟,代码写得更精简优美,不要去深究,若是想深刻,之后有时间再探究😂