类与对象绑定方法

今日内容概要

  • 小练习案列
  • 绑定方法
  • 非绑定方法(静态方法)
  • 如何隐藏属性
  • 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

posted @ 2021-12-03 19:47  Deity_JGX  阅读(67)  评论(0)    收藏  举报