今日内容概要
- 小练习案列
- 绑定方法
- 非绑定方法(静态方法)
- 如何隐藏属性
- property模块
![image]()
内容详细
小练习案列
# 计算一共产生了几个对象
class Student():
school = 'SH'
count = 0 # 专门用来计数
def __init__(self, name, age):
# self 就是>>>stu => {'name':'ly', 'age': 18, 'count':1}
# self 就是>>>stu1 => {'name':'ly1', 'age': 18, 'count':1}
# self 就是>>>stu2 => {'name':'ly2', 'age': 18, 'count':1}
self.name = name
self.age = age
# self.count = self.count + 1 错 对象空间中没有count 所以永远从类空间中拿 count=0 结果永远是 1
# Student.count += 1 # 要给类中的属性赋值加一 推荐用对象查找
self.__class__.count += 1 # self.__class__ = Student 要给类中的属性赋值加一
stu = Student('ly', 18)
stu2 = Student('ly1', 18)
stu3 = Student('ly2', 18)
print(stu.count) # 3
print(stu2.count) # 3
print(stu3.count) # 3
![image]()
绑定方法
绑定方法分两种:
1.绑定给对象的
2.绑定给类的
# 绑定给对象的方法(功能中需要用到对象)
先定义类
class Student():
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# 类中的方法,就是绑定给对象来使用的,对象来调用,会把自己当成第一个参数传到函数里面self
def tell_info(self):
print('name: %s,age:%s, gender:%s' % (self.name, self.age, self.gender))
stu = Student('ly', 18, 'male')
print(stu.name) # ly
stu.tell_info() # stu.tell_info(stu) name: ly,age:18, gender:male
# 绑定给类的方法(功能中需要用到类名)
先定义类
import settings
class Mysql():
def __init__(self, ip, port):
self.ip = ip
self.port = port
@classmethod # 该方法绑定给类了,以后有类来调用,会自动把类名当成第一个参数传过来cls
def from_conf(cls): # 一般默认参数用 cls
# cls => Oracle 其实就是 类名
# obj = Oracle(settings.IP, settings.PORT)
obj = cls(settings.IP, settings.PORT)
return obj
Mysql.from_conf() # 在调用时 类名 Mysql 就会当作参数传进去
![image]()
非绑定方法(静态方法)
# 既不绑定给类 也不绑定给对象
先定义类
class Student():
school = 'SH'
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod # 静态方法 在该功能中既用不到对象 也用不到类
def create_id(): # 实例化对象也不需要传值
import uuid
return uuid.uuid4() # 随机产生一串随机数 每次都不一样
stu = Student('ly', 18)
print(stu.create_id()) # 无需传值
print(Student.create_id()) # 无需传值
![image]()
如何隐藏属性
如何隐藏
"""
1.在类定义阶段,发生了语法上的变形 _类名__属性名
2.隐藏其实是 对外 不对内(类体内 依然可以找到)
3.只有在类定义阶段发生变形,其他情况都不发生变形
为何要隐藏
类里面的隐藏属性,类外部可以使用,但是目的不是让类外部可以使用
类外部想要使用,在类内部开放接口即可
主要为了 达到对外部数据的严格控制
"""
先定义类
class Student():
__school = 'SH' # 就相当于变形为 _Student__school => _类名__属性名
def __init__(self, name, age):
self.__name = name # 隐藏对象属性
self.age = age
def __tell_info(self): # 就相当于变形为 _Student__tell_info => _类名__函数名
print('name: %s, age: %s' % (self.__name, self.age))
def get_school(self): # 调用可以拿到__school 对外 不对内
return self.__school # self._Student__school
def set_school(self, v): # 增加方法来修改属性
if type(v) is not str:
print('数据类型不合法')
# if isinstance(v, str):
return
self.__school = v
stu = Student('ly', 18)
print(stu.name) # 隐藏后 在外部就拿不到 报错
print(stu.get_school()) # 获取school 正常获取 SH
Student.__school = 'sss' # 在隐藏之前 这样可以该属性 隐藏之后无法直接修改
print(stu.get_school()) # SH 依然是原始属性
print(stu.set_school('aaa')) # 'aaa'
![image]()
property装饰器
定义类
class Student():
__school = 'SH' # 隐藏了_Student__school => _类名__属性名
def __init__(self, name, age):
self.__name = name # name隐藏了
self.age = age
def __tell_info(self): # 隐藏了 _Student__tell_info => _类名__函数名
print('name: %s, age: %s' % (self.__name, self.age))
'''
stu = Student('ly', 18)
print(stu.name) # 报错 'Student' object has no attribute 'name'
因为name 被隐藏 无法直接在外部获取
# 想要获取 在类内部开放接口即可
def get_name(self):
return self.__name
stu = Student('ly', 18)
print(stu.get_name()) # ly
# 但是 我们想要的是名字 name
实际却是调用了方法 get_name 容易误导别人
所以为了将方法伪装成属性 引出 @property 装饰器
@property # 把方法伪装成属性
def get_name(self):
return self.__name
stu = Student('ly', 18)
print(stu.get_name) # ly 直接用方法名获取即可 不需要加括号 ly
# 为了将方法伪装的更像属性 方法名 get_name 可以写成 属性名 name
@property # 把方法伪装成属性
def name(self):
return self.__name
stu = Student('ly', 18)
print(stu.name) # ly
# 还可以让返回结果 通过格式化 更像属性
@property # 把方法伪装成属性
def name(self):
return "name:%s" % self.__name
stu = Student('ly', 18)
print(stu.name) # name:ly
# 修改属性 在类内部开放修改接口
@name.setter
def name(self, v): # 其他功能名都要和 @property 下功能名保持一致
if type(v) is not str: # 判断传的参数类型是否为字符串 也可以写 if isinstance(v, str):
print('数据类型不合法')
return
self.__name = v
stu = Student('ly', 18)
stu.name = 'aaa' # 修改
print(stu.name) # name:aaa 修改成功
内部调用了 @name.setter 修改接口
stu.name = 123 # 数据类型不合法 修改失败
print(stu.name) # name:ly 属性不变
# 删除属性 在类内部开放修改接口
@name.deleter
def name(self):
del stu.__name
print('删出成功')
del stu.name
print(stu.name) # 删出成功 + 没有该属性了会报错
'''
# 练习 获取Bmi指数
class Bmi():
def __init__(self, height, weight):
self.height = height
self.weight = weight
@property
def get_bmi(self):
return self.weight / (self.height ** 2)
bmi = Bmi(1.8, 70)
print(bmi.get_bmi) # 21.604938271604937 不用加括号调用获得属性结果
# 了解
class Student():
__school = 'SH' # _Student__school => _类名__属性名
def __init__(self, name, age):
self.__name = name
self.age = age
def __tell_info(self): # _Student__tell_info => _类名__函数名
print('name: %s, age: %s' % (self.__name, self.age))
def get_name(self):
return "name:%s" % self.__name
def set_name(self, v):
if type(v) is not str:
print('数据类型不合法')
# if isinstance(v, str):
return
self.__name = v
def del_name(self):
print('不让删')
xxx = property(get_name, set_name, del_name)
stu = Student('ly', 18)
stu.xxx = 'aaa' # .后面的名字必须和类中的属性名一致 会自动调用xxx属性内包含功能
print(stu.xxx) # name:aaa
name = property(get_name, set_name, del_name)
stu = Student('ly', 18)
stu.name = 'aaa'
print(stu.name) # name:aaa
![image]()