绑定方法、非绑定方法(静态方法)、隐藏属性、property装饰器

绑定方法、非绑定方法(静态方法)、隐藏属性、property装饰器

一、绑定方法

  • 特点:绑定给谁就应该由谁来调用,谁来调用就会将自己当做第一个参数传入

  • 1.但凡在类中定义一个函数,默认就是绑定给对象的,应该由对象来调用,会将对象当作第一个参数自动传入

  • 2.如果想要将函数绑定给类的话就需要用到绑定到类的方法:用classmethod装饰器装饰的方法。类中定义的函数被classmethod装饰过,就绑定给类,应该由类来调用,类来调用会类本身当作第一个参数自动传入

绑定方法分为2种:
	1. 绑定给对象的
    	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)
        stu.tell_info() # stu.tell_info(stu)
    
    2. 绑定给类的
    	
class Mysql():
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod  # 该方法绑定给类了,以后有类来调用,会自动把类名当成第一个参数传过来,cls
    def from_conf(cls):
        # cls => Oracle
        # obj = Oracle(settings.IP, settings.PORT)
        obj = cls(settings.IP, settings.PORT)
        return obj
 Mysql.from_conf()

二、非绑定方法

  • 特点:不与类和对象绑定,意味着谁都可以来调用,但无论谁来调用就是一个普通函数,没有自动传参的效果

  • 类中定义的函数被staticmethod装饰过,就成一个非绑定的方法即一个普通函数,谁都可以调用,但无论谁来调用就是一个普通函数,没有自动传参的效果

    • 注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

# 既不绑定给类,也不绑定给对象
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())
print(stu.create_id())

绑定方法、非绑定方法(静态方法)、隐藏属性、property装饰器

三、如何隐藏属性

  • 在python中用双下划线开头的方式将属性隐藏起来(设置成私有的),但其实这仅仅只是一种变形操作

# 1. 如何隐藏
		# 1. 如何隐藏
'''
    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):
        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

# 2、为何要隐藏属性
# - 隐藏数据属性为了严格控制类外部访问者对属性的操作
class People:

    def __init__(self,name,age):
        self.__name = name  # self._People__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("名字必须是字符串")
            return
        if type(age) is not int:
            print("年龄必须是数字")
            return
        self.__name = name
        self.__age = age

obj1 = People("jack",18)  
obj1.tell_info()     # <jack:18>

obj1.set_info("tom",28)  
obj1.tell_info()     # <tom:28>

obj1.set_info(123123123123,28)  # 名字必须是字符串
obj1.tell_info()     # <jack:18>

四、property装饰器

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:

过轻:低于18.5

正常:18.5-23.9

过重:24-27

肥胖:28-32

非常肥胖, 高于32

  体质指数(BMI)=体重(kg)÷身高^2(m)

  EX:70kg÷(1.75×1.75)=22.86

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)

p1 = People('jack',75,1.8)

# print(p1.bmi())  # 正常访问p1.bmi()需要加括号
# 23.148148148148145

print(p1.bmi)    #  用@property将bmi功能伪装成了数据属性
# 23.148148148148145

1、property的使用

class People:
    def __init__(self,name):
        self.__name = name
        
        
#    def get_name(self):
#        return self.__name 

    @property            # 1.查看行为
    def name(self):      # 被property装饰的name函数,其实是__name被藏起来了
        return self.__name

    @name.setter           # 
    def name(self,x):       # 2.修改行为
        if type(x) is not str:
            raise Exception("名字必须是字符串类型")
        self.__name = x

    @name.deleter      # 3.删除行为
    def name(self):
        print("不允许删除")

p1 = People('jack')
# print(p1.get_name)  # 访问

# 对应查看name行为   
print(p1.name)   # p1.name通过@property访问到的self.__name的属性

# 对应修改name行为
p1.name = 123 # 抛出异常
p1.name = "JACK"  # 正常修改
print(p1.name)

# 对应删除name行为
del p1.name
print(p1.name)

# ps: 配合property可以先将一个属性藏起来,__name这个属性被藏起来了,藏起来之后定义三个函数都叫name
#      这三个函数里面分别写上name的1、2、3的三种行为,跟操作一一对应



# 了解性知识点:这种方式也可以达到上面操作的效果

class People:
    def __init__(self,name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_name(self,x):
        if type(x) is not str:
            raise Exception("名字必须是字符串类型")
        self.__name = x

    def del_name(self):
        print("不允许删除")

    name = property(get_name,set_name,del_name)

p1 = People('jack')

绑定方法、非绑定方法(静态方法)、隐藏属性、property装饰器

上一篇:Lodop的JS模版代码、文档式模版 生成加载赋值博文索引


下一篇:Vue3响应式原理