Python绑定与非绑定方法、私有属性、property装饰器

一、绑定方法与非绑定方法

类中定义的函数分为两大类:绑定方法和非绑定方法

1.绑定方法

其中绑定方法又分为:绑定到对象的对象方法绑定到类的类方法
在类中直接定义的函数默认是绑定到对象的,
而为某个函数加上装饰器@classmethod后,该函数就绑定到了类。

'''1.绑定给对象的方法'''
class Student():
    school = '北京大学'
    # 绑定给对象的
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    '''绑定给对象来调用的'''
    def tell_info(self, username, password):
        print(f"'name':{self.name} 'age':{self.age} 'gender':{self.gender},{username} {password}")
    '''默认情况下,类在内部写方法是绑定给对象的,就由对象来调用,就会自动来传递参数'''
    '''默认情况下,类中直接定义的函数就是默认绑定给对象的,类要调用就需要传入该方法对应需要传递的参数,方法上面有些几个参数就传递几个'''

# 实例对象就会直接生产一个对象,因为默认绑定对象的,故不需要传递自身
stu = Student('jack', 18, 'male')
print(stu.name)  # jack

# 如何调用方法,对象来调用就对象来
'''
绑定给对象的方法有什么特殊之处:对象来调用方法,会把对象自己当成一个参数
传递给方法的第一个形参
'''
stu.tell_info('chen', 123)  # 其实相当于 stu.tell_info(stu,'chen',123)

'''
绑定给对象的方法,也可以用类来调用,但是需要传入方法相对应需要的几个参数,
也会包括self形参也是需要自己传递过来
'''
Student.tell_info(stu, 'chen', 123)


'''绑定给类的方法'''
class Mysql():
    # 传递给对象调用的
    def __init__(self, ip, port):
        self.ip = ip
        self.prot = port

    '''
    被@classmethod修饰的方法,默认会绑定给类,类调用就会把类自动当成第一个参数
    传递给方法的第一个形参cls
    对象也可以调用并且会自动将产生该对象的类当做第一个参数传入
        条件:
            1.加上一个装饰器@classmethod
            2.把方法的第一个形参改为cls
            3.外部调用该方法的时候使用类来调用即可
            4.绑定给类的方法中没有self这个参数了
            5.绑定给对象的方法中,就没有cls这个参数了
    '''
    @classmethod
    def from_func(cls):  # cls就是类
        return cls('127.0.0.1',3306)

# 实例对象
obj = Mysql('127.0.0.1', 3306)
print(obj.ip,obj.prot)  # 127.0.0.1 3306

# 类调用方法
print(Mysql.from_func().ip)  # 127.0.0.1
print(Mysql.from_func().prot)  # 3306

# 对象调用
print(obj.from_func().ip)  # 127.0.0.1
print(obj.from_func().prot)  # 3306

2.非绑定方法(静态方法static)

'''非绑定方法(静态方法static)'''
class Student():
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
        self.random_id = self.create_id()

    '''
    当你的方法(函数)中即不要对象绑定,也不要类绑定的时候,就可以把方法
    设置为静态方法,类能调用,对象也能调用,而且不需要传任何参数
    静态方法简单理解为之前一样正常的函数,如果这个函数中形参,那么类或对象调用就需要传参
    '''
    @staticmethod
    def create_id():
        import uuid
        # uuid.uuid4()随机生成16位数
        # 只要是生成固定的随机数,理论上就会有重复的几率
        return uuid.uuid4()

    def fun(self):
        '''如果你在方法中即需要对象,也需要类,就把方法绑定给对象'''
        print(self.__class__.__name__)  #  返回该对象类的名字,以字符串形式
        print(self.__class__)  # 返回该对象的类
        return self.__class__('chen',20,'male')  # 相当于Student()


stu = Student('jack',18,'male')
# 对象直接调用静态方法
print(stu.random_id)  # 这里是给init中设定了一个id
print(stu.create_id())
# 类直接调用静态方法
print(Student.create_id())
# 这里直接对象调用
stu.fun()
print(stu.fun().name)

二、私有(隐藏)属性和私有方法

'''
隐藏属性:
    1.隐藏属性在类的定义阶段发生了变形:_类名.__属性名
    2.隐藏属性在类的外部理论上是取不到的,但是非要取也是可以取到,
    但是在类的外部取隐藏之后的属性不是目的
    3.类属性、类方法、对象属性都额可以被隐藏
    4.隐藏属性对外不对内
    5.为什么要隐藏?
        就是可以对修改类内部的属性的时候,可以在类的内部做更好的限制,
        然后再类的内部开放一个公共的接口,对外返回内部隐藏的值
'''
class Student():
    # 隐藏的类属性
    __country = 'China'  # _Student__country
    __school = '哈佛大学'

    '在类中隐藏属性对外不对内,所以开辟一个接口来调用'
    def func(self):
        return self.__country

    @staticmethod  # 隐藏的静态方法
    def __index():  # _Student__index
        print('hello index')
    
    '在类中隐藏方法对外不对内,所以开辟一个接口来调用'
    @staticmethod
    def jk():
        Student._Student__index()

    '调用隐藏school的接口'
    def get_school(self):
        return self.__school

    '给调用隐藏接口的修改值设定一个判断'
    def set_school(self,v):
        if type(v) is str:
            self.__school = v
        else:
            print('修改的数据必须是字符串形式')

# 查询类的名称空间
# print(Student.__dict__) # 发现country发现了变形'_Student__country': 'China'

# 实例对象
stu = Student()
'''
变形后的数据目的也不是让在外部使用的,但是能在类的外部使用
这种是强制取的,这种方法不可取
'''
print(stu._Student__country)  # China 在外部取类内隐藏的属性
print(Student._Student__country) # China 在外部取类内隐藏的属性
stu._Student__index()  # hello index 在外部取类内隐藏的方法
Student._Student__index()  # hello index

'''这种是通过类内部的公共的接口来调用隐藏类的数据属性,是可取的'''
print(stu.func())  # China
print(Student.func(Student))  # China
'''通过类内部的公共的接口调用隐藏类的方法'''
stu.jk()  # hello index
Student.jk()  # hello index


'在类的内部开放一个公开的接口让类外调用隐藏属性'
print(stu.get_school())  # 哈佛大学
stu.set_school('北京大学')
print(stu.get_school())  # 北京大学
# 可以做着判断
stu.set_school(132)  # 判断不是字符串输出的

三、property装饰器

property装饰器的作用就是把类体内方法伪装成类属性来使用
这里的伪装的含义就是将原本需要加()的类方法不用加括号就可以直接获取结果

'''
property装饰器是一个内置的装饰器
主要是用来把类体内方法伪装成属性来使用
'''

'''第一种形式,使用类内部接口调用修改、删除、查看school数据值'''
class Student():
    __school = '哈佛大学'
    def get_school(self):
        return self.__school

    def set_school(self,v):
        if type(v) is str:
            Student.__school = v
        else:
            print('修改的数据必须是字符串形式')

    def del_school(self):
        del Student.__school

stu = Student()
print(stu.get_school())  # 哈佛大学
stu.set_school('北京大学')
print(stu.get_school())  # 北京大学
stu.del_school()  # 删除school数据
print(stu.get_school())  # 查看类中显示没有school这个数据了


print('============')

'''第二种形式,通过装饰器,也是实现了第一种方式的所有功能,并且做了伪装'''
class Student():
    __school = '哈佛大学'
    @property
    def school(self):
        return self.__school

    @school.setter
    def school(self,v):
        if type(v) is str:
            Student.__school = v
        else:
            print('修改的数据属性得是字符串形式')

    @school.deleter
    def school(self):
        del Student.__school

stu = Student()
print(stu.school)  # 哈佛大学
stu.school = '北京大学'
print(stu.school)  # 北京大学
del stu.school
print(stu.school)

print('============')

'''第三种形式也是用装饰器,但是可以让他不伪装,随便使用什么函数名'''
class Student():
    __school = '哈佛大学'  # 隐藏数据属性
    def get_school(self):
        return self.__school

    def set_school(self, v):
        if type(v) is str:
            Student.__school = v
        else:
            print('修改的数据必须是字符串形式')

    def del_school(self):
        del Student.__school

    '''有顺序要求'''
    # 这个变量名也是随便命名的
    school = property(get_school, set_school, del_school)


stu = Student()
print(stu.school)
stu.school = '北京大学'
print(stu.school)
del stu.school
print(stu.school)



'''
拓展了解
体质指数(bmi)  = 体重(kg) ÷ 身高^2(米)
'''
class People():
    def __init__(self, height, weight):
        self.height = height
        self.weight = weight

    @property  # 装饰器property作用是把类体功能伪装成属性来使用
    def bmi(self):
        return self.weight / (self.height ** 2)

jck = People(1.8, 62)
print(jck.bmi)  # 19.1358024691358
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值