''' 一。封装 1、什么是封装 封:属性对外是隐藏的,但对内是开放的 装:申请一个名称空间,往里装入一系列名字、属性 2、为什么要封装 封装数据属性的目的 1 首先定义属性的目的就是为了给类外部的使用者使用的 2 隐藏之后为了不让外部使用者直接使用,需要类内部开辟一个借接口 3 然后让类外部的使用通过接口来间接的操作隐藏的属性 4 精髓在于:我们可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作 封装函数属性目的 1首先定义属性的目的就是为了给类外部使用者使用的 2 隐藏函数属性是为了不让外部直接使用,需要在内部开辟一个接口 3 然后用接口去调用隐藏的功能 4 精髓在于:隔离了复杂度 3、如何封装 如何隐藏:在属性前加上__开头 1 这种隐藏仅仅是一种语法上的变形操作 2 这种语法上的变形只是在类定义阶段发生一次,因为类体代码仅仅只在类的定义阶段检测一次 3 这种隐藏是对外不对内的,即再内的内部可以直接访问,而在类的外部则无法直接访问, 原因是再类的定义阶段,类体代码统一发生了一次变形 4、如果不想让子类的方法覆盖父类的,可以在该方法名前加一个__开头 ''' # class People: # __country='china'#_People__coutry='china' # # __n=100#_People__n=100 # 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) #People._People__courtry # print(self.__name) #self._People__name # # peo1=People('lin',18,'male') # # People.eat(123)#间接调用 # # # print(People.__country)#不能直接访隐藏的属性 # # peo1.eat()#间接调用 # # print(peo1.__name)#无法直接操作 # # # # print(People.__dict__)#查看属性的字典 # print(People._People__country)#利用存的语法方法可以查看,不过失去其隐藏的意义 # People.__x=1 #后加的值无法进行语法的变形 # print(People.__dict__) # # peo1=People('egon',18,'male') # peo1.__x=111 # print(peo1.__dict__)#因为后加的没有语法变形,所以可以直接修改 # # 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') # # obj=Bar() # obj.f2() #先打印 foo.f2 后打印 foo.f1 #因为在类在定义阶段就将类体代码变形好了,所以只能在父类中找 # 如果不想让子类的方法覆盖父类的,可以在该方法名前加一个__开头 class People: def __init__(self,name,age): self.__name=name self.__age=age def tell_info(self): print('%s:%s'%(self.__name,self.__age)) def set_info(self,name,age): if type(name) is not str: raise TypeError('用户名必须为str类型') if type(age) is not int: raise TypeError('年龄必须为int类型') self.__name=name self.__age=age peo1=People('egon',18) peo1.name=123 #新增的值 {'_People__name': 'egon', '_People__age': 18, 'name': 123} # peo1.age #不能直接找到隐藏的属性 peo1.tell_info()#通过间接调用接口 print(peo1.__dict__) peo1.set_info('egon',19)
# peo1.tell_info() #通过接口将信息修改
# 二,property 装饰器 # 用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用 # class People: # def __init__(self,name,weight,height): # self.name=name # self.weight=weight # self.height=height # # @property#直接将bmi伪装成数据属性直接 对象.函数名的方式 # def bmi(self): # return self.weight/(self.height**2) # # peo1=People('egon',75,1.80) # peo1.height=1.85 #更改值 # print(peo1.bmi)#用类的函数 # class People: # def __init__(self,name): # self.__name=name # # @property #查看obj.name # def name(self): # return '<名字是:%s>'%self.__name # # @name.setter #修改obj.name=值 必须之前有@property装饰器才可 # def name(self,name): # if type(name) is not str: # raise TypeError('必须为字符串类型') # self.__name=name # # @name.deleter #删除 del obj.name 必须前有@property装饰器才可 # def name(self): # # raise PermissionError('不能删') # del self.__name # # peo1=People('egon') # print(peo1.name) # # peo1.name='lin' # print(peo1.name) # # del peo1.name class People: def __init__(self,name): self.__name=name def tell_name(self): return '<名字是:%s>'%self.__name def set_name(self,name): if type(name)is not str: raise TypeError('名字必须是str类型') self.__name=name def del_name(self): print('不让删除') name=property(tell_name,set_name,del_name) #不建议使用此方式 peo1=People('egon') print(peo1.name) peo1.name='egon' print(peo1.name) del peo1.name
''' 一。绑定方法和非绑定方法 1、绑定方法 特性:绑定给谁就应该有谁来调用,谁来调用就会将谁当作第一个参数自动传入 《 精髓在于自动传值》 绑定方法分为两类: 1 绑定给对象的方法 在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的 2 绑定给类的方法: 在类内部定义的函数如果被装饰器@classmethod装饰, 那么则是绑定给类的,应该由类来调用的,类来调用就自动将类当做第一个参数自动传入 2、非绑定方法 类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法 既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用 但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数 3、应用 1.如果函数体代码需要用外部传入的类,则应该将函数定义成绑定给类的方法 2.如果函数体代码需要用外部传入的对象,则应该将函数定义成绑定给对象的方法 3.如果函数体代码即不需要外部传入的类也不需要外部传入的对象,则应该将函数定义成 非绑定方法、普通函数 ''' # class Foo: # @classmethod #给类建立绑定方法 # def f1(cls): # print(cls) # def f2(self): # print(self) # # obj=Foo() # print(obj.f2) # print(Foo.f1)#;两个都建立了绑定方法 # # Foo.f1() # print(Foo) # # # 1、f1绑定给类的 # # 了解:绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的仍然是类 # # print(Foo.f1) # # print(obj.f1) # Foo.f1() # obj.f1() # # # # 2、f2是绑定给对象用的 # obj.f2() # Foo.f2(obj)#在用的时候需自己传入参数 import settings import uuid class Mysql: def __init__(self,ip,port): self.uid=self.create_uid() self.ip=ip self.port=port def tell_info(self): print('%s:%s'%(self.ip,self.port)) @classmethod def from_conf(cls): return cls(settings.IP,settings.PORT) @staticmethod def func(x,y): print('不与任何人绑定') @staticmethod def create_uid(): return uuid.uuid1() # # 默认的实例化方式:类名(,,,) obj=Mysql('10.10.1.9',3307) #一种新的实例化方法:从配置文件中读取配置完成实例化 # obj1=Mysql.from_conf() # obj1.tell_info() # # obj.func(1,3) # Mysql.func(3,3) # # print(obj.func) # print(Mysql.func) # # print(obj.uid)