封装property和绑定方法
Posted smart1san
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了封装property和绑定方法相关的知识,希望对你有一定的参考价值。
一、封装
1.定义
封:指的是该属性对外是隐藏的,但是对内部是开放的
装:申请一个名称空间,往里边丢名字和属性
2.为什么要有封装
2.1 封装数据属性的目的:
首先定义数据属性的目的就是为了给类外部使用的,隐藏之后就是为了不让外部直接使用,需要通过调用类内部开通的接口来使用;然后类外部需要用到这个功能的时候,可以通过这个接口来间接的调用并操作这个隐藏属性。
精髓:我们可以在该接口上附加上任何我们想要的逻辑与功能,从而达到严格控制使用者对属性的操作。
2.2 封装函数属性的目的:
定义函数属性的目的就是为了给类外部使用的,隐藏函数属性的目的就是为了不让外部直接使用,须在类的内部开辟一个专门的接口;外部需要使用是,也是需通过这个接口来间接的调用并操作这个隐藏的函数属性。
精髓:隔离了复杂的程度
3.如何做到封装
可以在需要隐藏的属性前面加上__开头
解释:
3.1 这种隐藏仅仅是一种语法上的变形操作。
3.2 变形操作只在类的定义阶段发生一次,因为类体代码仅仅只在定义阶段检测一次。
3.3 这种隐藏是对外不对外的,即在类的内部可以直接访问而在外部不能直接访问;究其根本原因是在类的定义阶段,类体的代码发生了一次统一的变形。
3.4 如果不想让子类的方法覆盖父类的,可以直接在子类的方法名前加上__开头,隐藏其属性。
1 class People(): 2 def __init__(self,name,age): 3 self.__name=name 4 self.__age=age 5 def tell_info(self): 6 print(‘%s - %s‘%(self.__name,self.__age)) 7 def reset_info(self,name,age): 8 self.__name = name 9 self.__age = age 10 if type(name) is not str: # 在接口上可以添加我们想要的逻辑 11 raise NameError(‘name must be string‘) 12 if type(age) is not int: 13 raise TypeError(‘age must be integer‘) 14 15 p1=People(‘大仙‘,999) 16 # print(p1.name) # 外部已经访问不到该属性了 17 p1.tell_info() 18 p1.reset_info(‘瓶盖‘,9) # 通过类内部定义的特定接口来更改数据 19 p1.tell_info()
二、property
property 将被装饰的方法伪装成一个数据属性,这样在使用时就可以不用加括号而直接引用。
class People: def __init__(self,name,height,weight): self.name=name self.weight=weight self.height=height @property def BMI(self): return self.weight/(self.height**2) p=People(‘黄山‘,1.7,75) print(p.BMI) # 可以不用加括号而直接调用
1 class People: 2 def __init__(self,name): 3 self.__name=name 4 5 # 将name函数伪装成一个普通的数据属性 6 @property # 查看obj.name 7 def name(self): 8 return ‘your name is %s‘ %self.__name 9 10 @name.setter # 修改obj.name的值 11 def name(self,name): 12 if type(name) is not str: 13 raise NameError(‘your name must be str ‘) 14 self.__name=name 15 # 相当于在类的内部提供了一个专门修改名字的接口 16 17 @name.deleter # 删除obj.name 18 def name(self): 19 raise PermissionError(‘Deleting the name is not permission‘) 20 # del self.__name # 若要删除obj.name这个属性,可以注释掉上面的raise error, 21 # 相当于在类的内部提供了一个专门删除obj.name的接口 22 23 p=People(‘大佬‘) 24 print(p.name) # 可以不直接加括号而直接引用 25 26 # p.name=123 27 # print(p.name) #NameError: your name must be str 28 29 del p.name #NameError: your name must be str
三、绑定方法和非绑定方法
1.定义
1.1 绑定方法
绑定方法分成两类:
1.1.1 绑定给对象
在类内部定义的函数且没有被任何函数装饰器修饰的,这种就是默认绑定给对象的
1.1.2 绑定给类
在类内部定义的函数如果被装饰器@classmethod 装饰的,这个函数就是绑定给类的,就应该由类来调用,类来调用就会将类当作第一个参数自动传入。
1.1.3 绑定方法的特性:
绑定给谁就应该由谁来调用,谁来调用就会将谁当成第一个参数自动传入<其精髓就在于:自动传值>
1.2 非绑定方法
类中定义的函数如果被装饰器@staticmethod 装饰,那么该函数就变成非绑定方法。
函数如果没有被绑定,则意味着类和对象皆可调用,但无论谁来调用,都没有自动传值的效果,就是一个普通的函数,这种情况则应该传入相应的参数。
2. 如何使用
如果函数体代码需要使用外部传入的类,则应该将函数定义成绑定成给类的方法
如果函数体代码需要使用外部传入的对象,则应该将函数定义成绑定给对象的方法
如果函数体代码既不需要使用外部传入的类,也不需要使用外部传入的对象,那么应该将函数定义成非绑定方法/普通函数。
1 import settings 2 import uuid 3 4 class mysql(): 5 def __init__(self,ip,port): 6 self.uuid=self.create_uuid() 7 self.ip=ip 8 self.port=port 9 10 def get_info(self): 11 print(‘%s - %s‘%(self.ip,self.port)) 12 13 @classmethod 14 def from_settings(cls): 15 return cls(settings.ip,settings.port) 16 17 @staticmethod 18 def create_uuid(): # 非绑定方法,所以不需要参数 19 return uuid.uuid4() 20 21 # 默认的实例化方式 22 obj=Mysql(‘192.168.0.0‘,3306) 23 obj.get_info() # 这种情况下函数是已经执行了, 24 # 所以不必在用print(obj.get_info())了, 25 # 否则在输出结果的同时,会收到一个函数的默认返回值 26 27 # 一种新的实例化方式,从配置文件中读取出配置完成实例化 28 obj=Mysql.from_settings() 29 obj.get_info() 30 31 # 若函数是非绑定方法,则类和对象皆可调用 32 obj.create_uuid() 33 Mysql.create_uuid()
ip=‘192.168.0.0‘ port=3306
以上是关于封装property和绑定方法的主要内容,如果未能解决你的问题,请参考以下文章
python 3全栈开发-面向对象之绑定方法(classmethod与staticmethod的区别)多态封装的特性property
如何使用 Isvisible Property 的绑定方法?
Vue报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object 的解决方法(代码片段