封装、property特性及绑定与非绑定方法

1、封装

(1)什么是封装?

封:属性对外是隐藏的,但对内是开放的;

装:申请一个名称空间,往里面装入一系列名字/属性

(2)为什么要封装?

封装数据属性的目的

首先定义属性的目的就是为了给类外部的使用者使用的

隐藏之后是为了不让外部使用直接使用,需要类内部开辟一个接口

然后让类外部的使用通过接口来间接的操作隐蔽的属性

精髓在于:我们可以在接口之上附加任意逻辑,从而严格严格控制使用者对属性的操作;

封装函数属性

首先定义属性的目的就是为了给类外部的使用使用的

隐藏函数属性是为了让使用者不直接使用,在类内部开辟一个接口,在接口内部调用隐蔽的功能

精髓在于:隔离了复杂度

(3)如何封装

如何隐藏:在属性前加上__开头

1、这种隐藏仅仅只是一种语法上的变形操作;

2、这种语法上的变形只是在类定义阶段发生一次,因为类体代码仅仅只在类定义阶段检测一次;

3、这种隐藏是对外不对内的,即在类的内部可以直接访问

,而在类的外部则无法直接访问,原因是在类定义阶段,类体代码统一发生了一次变形

(4)、如果不想让子类的方法覆盖父类的,可以将该方法名前加上一个__开头

如何隐藏
# class people:
# __country= 'china' # 在要隐藏的属性前加上__
# def __init__(self,name,age,sex):
# self.__name= name #在定义阶段代码发生了变形 self._people__name= name
# self .age= age
# self .sex= sex
#
# def eat(self):
# print('eat....')
# print(people .__country ) #在类内部可以访问 # peo= people('egon',18,'male')
#people .__country #在类外部无法访问
# print(people.__dict__ )
#隐藏的原理:在类定义阶段属性名__country 变成了_people__country
# print(people._people__country) #这样是可以访问到隐藏后的属性的

如果不想让子类的方法覆盖父类的,可以将该方法名前加上一个__开头

class Foo:
def __f1(self): #_Foo_f1
print('Foo.f1') def f2(self):
print('Foo.f2')
self .__f1() #self._Foo_f1 class Bar(Foo):
def __f1(self): #_Bar_f1
print('Bar.f1')
#print(Bar.mro())
obj = Bar()
obj.f2()

2、Property 装饰器

property装饰器用于将被装饰的方法伪装成一个数据类型,在使用时不用加括号而直接引用

class people:
def __init__(self,name):
self.__name= name @property #伪装成数据属性查看
def name(self):
return self .__name @name.setter #在原来函数name上进行修改操作
def name(self,name):
if type(name) is not str:
print('名字必须是str类型')
self .__name= name #把原来的属性self.__name改成name @name.deleter #删去操作
def name(self):
#print('不让删')
del self.__name peo= people ('qqc') #建对象 # print(peo.name) #查看
peo.name= 'QQC' #修改操作
print(peo.name)
# del peo.name #删除操作
# print(peo.__dict__ )

3、绑定方法与非绑定方法

(1)绑定方法

特性:绑定给谁就应该由谁来调用,谁里啊调用就会将谁当做第一个参数自定传入

注:自动传值

绑定方法分为两类:

1.1 绑定给对象的方法

在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的

1.2 绑定给类的方法

在类内部定义的函数如果被装饰器@classmethod装饰,

那么则是绑定给类的,应该由类来调用,类来调用就自动将类当做第一个参数自动传入

(2)非绑定方法

类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法

即不与类绑定,又不与对象绑定,意味着类与对象都可以来调用

但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数

应用:

函数体代码需要用外部传入的类,则应该将该函数定义成绑定给类的方法;

函数体代码需要用外部传入的对象,则应该将该函数定义成绑定给对象的方法;

如果函数体代码即不需要外部传入的类也不需要外部传入的对象,则应该将该函数定义成非绑定方法/普通函数

#绑定方法
class Foo:
@classmethod
def f1(cls):
print(cls)
def f2(self):
print(self) obj = Foo()
# print(obj.f2)
#1、f1是绑定给类的,应该由类来调用,但其实对象也可以调用,但自动传入的参数仍然是类
# Foo.f1()
#2、f2是绑定给对象的
# obj.f2()

例子:从配置文件中实例化

import settings
class mysql:
def __init__(self,ip,port):
self.ip= ip
self.port= port def tell_info(self):
print(self.ip ,self .port) @classmethod
def from_conf(cls): #与类绑定,自动传入类
return mysql(settings.IP,settings.PORT) @staticmethod #非绑定方法,无自动传值
def func():
print('不与任何人绑定') #默认实例化方式:类名(。。。)
obj= mysql('10.10.0.9',3307) #一种新的实例化方式,从配置文件中读取配置完成实例化
obj1= mysql.from_conf()
obj1.tell_info()
obj1.func()
上一篇:JAVA中handleEvent和action的区别


下一篇:PHP代码审计笔记--任意文件下载漏洞