"在封装的基础上, 我们可以将装到对象或者类中的属性给隐藏起来"
"注意: "
"1. 在定义类或者初始化对象, 在属性之前加 __ , 就会将该属性隐藏起来"
" 但该隐藏只是一种变形,_类__属性名, 并没有真正的隐藏起来"
"2. 该变形操作是在定义阶段扫描语法是发生的变形, 类定义后添加的__开头并不会影响"
"3. 该隐藏是对外不对内的"
"4. 在继承中, 父类如果不想让子类覆盖自己的方法, 可以将方法定义为私有的"
"例" class Student: __school = "oldboy" # 会变形为 _Student__school def __init__(self,name,age,sex): self.__name = name self.age = age self.sex = sex def __choose(self): print("%s 正在...." % self.__name) # 初始化一个对象 obj = Student("chen",18,'male') obj.__age # 这种方式已经访问不到里面的age了 obj.__name = 18 # 这种方式是新增值, 不是改里面的值 查看类包含属性使用 __dict__ 方法 print(obj.__dict__) # _Student__name 这个是变形后的属性名 根据这个属性名可以在外部找到相应的值, "也就是说, python不是完全封闭的"
" 隐藏属性的意义何在, "
"1. 把数据属性隐藏起来的意义是: 在类内开放接口, 让外界通过即可来操作"
"属性值来严格控制外界对属性的操作"
这样就需要有一个特定的接口来进行访问, 修改, 和删除
class Student: def __init__(self,name,age,sex): self.__name = name self.age = age self.sex = sex def __choose(self): print("%s ...." % self.__name) # 需要访问名字 def get_name(self): return self.__name # 需要修改名字 def set_name(self,name): self.__name = name # 初始化对象 obj = Student('chen',18,'male') # print(obj.get_name()) # 查看名字 obj.set_name('shao') # 修改名字 print(obj.get_name()) # 查看
装饰器property的使用
"装饰器解释: 是一种特殊的属性, 访问时会执行一段函数, 然后返回值"
"代码实现" class Student: def __init__(self,name,height,weight): self.name = name self.height = height self.weight = weight @property # 添加装饰器 def bmi(self): # 评测身体素质 return self.weight / (self.height ** 2) p = Student('chen',1.71,58) # 有装饰器后调用时不加括号 print(p.bmi)
"property的第一种用法 也是新式用法"
"property的第一种用法 也是新式用法" class People: def __init__(self,value): self.__value = value @property def name(self): # obj.name访问的是self.__value(这个位置的值) return self.__value @name.setter def name(self,value): # 该值, 同上访问处理 self.__value = value @name.deleter def name(self): # 删除值, 同上访问 del self.__value p = People('chen') print(p.name) p.name = 'shao' print(p.name) del p.name print(p.name) # 没有值访问会抛出异常 "AttributeError: 'People' object has no attribute '_People__value'"
"property的第一种用法 老式方法"
"property的第一种用法 老式方法" class People: def __init__(self,value): self.__value = value def get_name(self): return self.__value def set_name(self,name): self.__value = name def del_name(self): del self.__value # 记住: 顺序不能变, 按照 查--> 修改--> 删除 这个顺序,乱了会抛出异常 name = property(get_name,set_name,del_name) # 操作都一样, 只是设计时有所变化 p = People('chen') print(p.name) p.name='shao' del p.name
"绑定方法与非绑定方法"
" 绑定方法: 谁来调用就将谁当做第一个参数传入"
"1. 绑定给对象的方法: 类中定义的函数默认就是绑定给对象的方法, 应该是由对象调用"
" 会把对象当做第一个参数传入"
"2. 绑定给类的方法; 在类中的函数加上装饰器 @classmethod, 该函数就会绑定给类"
" 该函数由类来调用, 会把类当做第一个参数传入, "
"当然这不是绝对的, 两个是可以互相调用的, 只是一种规定而已, 强制调用也不会影响"
" 非绑定方法: 既不与类绑定也不与对象绑定, 就是一个普通的函数, 谁都可以来调用"
" 没有自动传参效果, 在函数上添加装饰器 @staticmethod"
"例: " class People: def __init__(self,name): self.name = name @classmethod def f1(cls): # 绑定类 当做普通函数使用 print(cls) @staticmethod def f2(x,y,z): # 非绑定方法 print(x,y,z) p = People('chen') p.f1() # <class '__main__.People'> p.f2(2,3,4)
" 新模块 uuid 是生成随机id的工具"
" 新模块 uuid 是生成随机id的工具" import uuid IP='127.0.0.1' PORT = 3306 class MySQL: def __init__(self,ip,port): self.mid = self.__create_id() self.ip = ip self.port = port def tell_info(self): print("地址:%s [%s - %s]"% (self.mid,self.ip,self.port)) @staticmethod def __create_id(): # 要使用非绑定方法才能拿到通用的id, 因为这个不是对象特有的 return uuid.uuid4() # 通过类绑定 第一个传值给类 @classmethod def form_m(cls): return cls(IP,PORT) p= MySQL('127.0.0.1',3306) p.tell_info() s = MySQL.form_m() s.tell_info()