类的封装,property装饰器的作用,绑定方法与非绑定方法,反射,
类的封装
''' 1、什么封装 封:属性对外是隐藏的,但对内是开放的 装:申请一个名称空间,往里装入一系列名字/属性 2、为什么要封装 封装数据属性的目的 首先定义属性的目的就是为了给类外部的使用者使用的, 隐藏之后是为了不让外部使用直接使用,需要类内部开辟一个接口 然后让类外部的使用通过接口来间接地操作隐藏的属性。 精髓在于:我们可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作 封装函数属性 首先定义属性的目的就是为了给类外部的使用者使用的, 隐藏函数属性是为了不让外部直接使用,需要类内部开辟一个接口 然后在接口内去调用隐藏的功能 精髓在于:隔离了复杂度 3、如何封装 ''' # 如何隐藏:在属性前加上__开头 #1、 这种隐藏仅仅只是一种语法上的变形操作 #2、 这种语法上的变形只在类定义阶段发生一次,因为类体代码仅仅只在类定义阶段检测一次 #3、 这种隐藏是对外不对内的,即在类的内部可以直接访问,而在类的外则无法直接访问,原因是 # 在类定义阶段,类体内代码统一发生了一次变形 #4、 如果不想让子类的方法覆盖父类的,可以将该方法名前加一个__开头 # class People: # __country='China' #_People__country='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__country # print(self.__name) #self._People__name # People.eat(123) # print(People.__country) # peo1=People('egon',18,'male') # peo1.eat() # print(peo1.__name) # print(People.__dict__) # print(People.__country) # print(People._People__country) # People.__x=11 # print(People.__dict__) # peo1=People('egon',18,'male') # print(peo1.__dict__) # 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() 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: # print('用户名必须为str类型') # return raise TypeError('用户名必须为str类型') if type(age) is not int: # print('年龄必须为int类型') # return raise TypeError('年龄必须为int类型') self.__name=name self.__age=age peo1=People('egon',18) # peo1.name=123 # peo1.age # peo1.tell_info() peo1.set_info('egon',19) # peo1.tell_info()
property装饰器的作用
# property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用 # class People: # def __init__(self,name,weight,height): # self.name=name # self.weight=weight # self.height=height # # @property # def bmi(self): # return self.weight / (self.height ** 2) # # peo1=People('egon',75,1.8) # # 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=值 def name(self,name): if type(name) is not str: raise TypeError('名字必须是str类型傻叉') self.__name=name @name.deleter #删除del obj.name def name(self): # raise PermissionError('不让删') print('不让删除傻叉') # del self.__name peo1=People('egon') # print(peo1.name) # print(peo1.name) # peo1.name='EGON' # print(peo1.name) del peo1.name
绑定方法与非绑定方法
''' 1、绑定方法 特性:绑定给谁就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入 《《《精髓在于自动传值》》》 绑定方法分为两类: 1.1 绑定给对象方法 在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的 1.2 绑定给类的方法: 在类内部定义的函数如果被装饰器@classmethod装饰, 那么则是绑定给类的,应该由类来调用,类来调用就自动将类当作第一个参数自动传入 2、非绑定方法 类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法 既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用 但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数 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.0.9',3307) # 一种新的实例化方式:从配置文件中读取配置完成实例化 # obj1=Mysql.from_conf() # obj1.tell_info() # obj.func(1,2) # Mysql.func(3,4) # print(obj.func) # print(Mysql.func) print(obj.uid)
反射
什么是反射 通过字符串来操作类或者对象的属性
# d = {'name': '123'} # print(isinstance(d,dict)) # 是不是同一类型 # class Foo: # pass # class Bar(Foo): # pass # # print(issubclass(Bar,Foo)) # Bar 是不是Foo的子类 # # # class People: # def __init__(self, name, ip, port): # self.name = name # self.ip = ip # self.port = port # # # def get(self): # print('GET function') # # def see(self): # print('SEE function') # # def run(self): # while True: # chioce = input(">>>>>>").strip() # if hasattr(self, chioce): # monthod = getattr(self, chioce) # monthod() # else: # print("没有这个命令") # monthod = getattr(self,chioce, None) # if monthod is None: # print('没有这个命令') # else: # monthod() # # # # # # peo1 =People('egon', '12','222.10') # hasattr(peo1,'see') # 有没有这个属性 有就返回True # getattr(peo1,'see',None) # 给我这个属性, 没有就返回None # setattr(peo1,'name','alex') # 改掉这个特征 # delattr(peo1,'name') # 删除这个属性 , 只能删除特征,不能删除函数 # print(hasattr(peo1,'run')) # class People: # def __init__(self, name, age): # self.name = name # self.age = age # # def __str__(self): # 自动触发,在打印时 # return '%s\t%s' % (self.name, self.age) # # # peop1 = People('egon', '18') # peop2 = People('alex', '81') # print(peop1) # print(peop2) # class People: # def __init__(self, name, age): # self.name = name # self.age = age # self.f = open(r'a.txt', 'rt', encoding='utf-8') # # def __del__(self): # # del 在回收python文件时自动触发,把不属于python的资源也一起关闭,相当于临终遗言 # print('>>>>>>') # self.f.close() # # # obj = People('egon', 18) # # print(123)