zoukankan      html  css  js  c++  java
  • 静态属性 类的绑定方法 静态方法

    静态属性 类的绑定方法 静态方法

    静态属性property

    作用


     

      静态属性就是将类中方法封装,在python中利用@property语句实现。

      @property的作用实际上非常强大。它可以允许将某一方法不用加括号就直接调用,看起来就跟访问属性一样,也可以控制对某一属性的增删改查之类的操作。它有一个别称叫做“数据描述符” 。

      Ps:@property最最单纯的用法应该是与封装相关..属于面向对象封装里的一个特性。其实在写分页插件的时候,我就实际用到过@property这个方法,它其实就是一个数据描述符类。 关于具体的内部实现原理这里不太方便做介绍,会在后面讲描述符的时候专门提出来分析。

     

    print(property)  # <class 'property'>

     

    伪装方法为属性的案例


      BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标,计算公式为:

     

      体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg÷(1.75×1.75)=22.86

     

      身高或体重是不断变化的,因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能,为此Python专门提供了一个装饰器@property可以将类中的函数“伪装成”对象的数据属性(实例属性),对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果,例如:

     

    class People:
    
        def __init__(self,name,weight,height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property
        def bmi(self):
            """BMI在18.bai5至24.9时属正常范围,BMI大于25为超重du,BMI大于30为肥胖。zhi"""
            return self.weight / (self.height**2)
    
    obj=People('lili',75,1.85)
    print(obj.bmi) # 21.913805697589478
    
    # 看起来是在调用实例属性,实际上是拿到的实例绑定方法处理完毕后的结果。

     

    控制属性的增删改查案例


     

    class Foo:
    
        def __init__(self,name):
            self.__name = name
    
        @property  # 当用户访问 obj.name 发生的事...
        def name(self):
            return "你的偶像:[{0}],永远滴神...".format(self.__name)  # 可以看到返回的是 __name
    
        @name.setter  # 当用户设置 obj.name 发生的事儿...
        def name(self,value):
            val = "UZI"
            if value != val or value != "UZI":
                print("乌兹!永远的神!不允许修改其他值!")
            else:
                self.__name = val
    
        @name.deleter  # 当用户删除 obj.name 发生的事儿...
        def name(self):
            print("不允许删除!")
    
    f1 = Foo("乌兹")   # 开始设置,相当于增..触发 @name.setter 下的函数运行
    print(f1.name)    # 访问时候触发 @property 下的函数运行
    f1.name = "UZI"   # 修改设置.. 触发 @name.setter 下的函数运行
    print(f1.name)    # 访问时候触发 @property 下的函数运行
    f1.name = "bang"  # 设置的是bang,不会成功,触发 @name.setter 下的函数运行
    del f1.name  # 删除时候触发 @name.deleter 下的函数运行
    
    # ==== 执行结果 ====
    
    """
    你的偶像:[乌兹],永远滴神...
    你的偶像:[UZI],永远滴神...
    乌兹!永远的神!不允许修改其他值!
    不允许删除!
    """
    property实例化实现控制属性增删改查方式一
    class Foo:
    
        def __init__(self,name):
            self.__name = name
    
        def get_name(self):
            """当用户访问 obj.name 发生的事..."""
            return "你的偶像:[{0}],永远滴神...".format(self.__name)  # 可以看到返回的是 __name
    
        def set_name(self,value):
            """当用户设置 obj.name 发生的事儿..."""
            val = "UZI"
            if value != val or value != "UZI":
                print("乌兹!永远的神!不允许修改其他值!")
            else:
                self.__name = val
    
        def del_name(self):
            """用户删除 obj.name 发生的事儿..."""
            print("不允许删除!")
    
        name123 = property(get_name,set_name,del_name) # 第一个位置是获取,第二个位置是设置与新增,第三个位置是删除
    
    # ==== 注意 : 下面全部要改成 name123 ====
    
    f1 = Foo("乌兹")   # 开始设置..相当于增,触发 set_name的函数运行
    print(f1.name123)    # 访问时候触发 get_name 的函数运行
    f1.name123 = "UZI"   # 修改设置.. 触发 set_name 的函数运行
    print(f1.name123)    # 访问时候触发 get_name 的函数运行
    f1.name123 = "bang"  # 设置的是bang,不会成功,触发 @name.setter 下的函数运行
    del f1.name123  # 删除时候触发 del_name 的函数运行
    
    # ==== 执行结果 ====
    
    """
    你的偶像:[乌兹],永远滴神...
    你的偶像:[UZI],永远滴神...
    乌兹!永远的神!不允许修改其他值!
    不允许删除!
    """
    property实例化实现控制属性增删改查方式二

     

      目前,就了解这两个即可。实际上关于@property的玩法还有非常非常多。在讨论描述符的时候会详细举例...

     

    类的绑定方法classmethod

    作用


     

      利用@classmethod语句,将某个方法只和类绑定而不和实例绑定,效果就是该方法能够获取到类的__dict__,当通过实例调用时也是拿的类的__dict__而拿不到实例的__dict__,因此也被称为类的绑定方法。

      Ps:使用场景较少

     

    类的绑定方法实例


     

    # 需求:打印该类下的所有类属性
    
    class School(object):
    
        name = "学校类"
        addr = "任意地方"
        nature = "虚拟"
    
        def __init__(self,name):
            self.name = name
    
        @classmethod
        def show_attr(cls): # cls即类,说明传入的应当是一个类。
            """打印所有的类属性"""
            print([i for i in cls.__dict__.values() if not str(i).startswith("<") and i and not str(i).startswith("__")])
            # 注释: 列表推导式复习 由于有方法,所以不能以 < 开头 ,不能是None, 不能以__开头的内容打印出来
    
    # ==== 正确的打开方式,类的绑定方法应该由类调用 ====
    
    School.show_attr()
    
    # ==== 不推荐使用实例对象去调用类的绑定方法,因为它根本拿不到实例对象的 __dict__ 但是Python依然不会抛出异常 ====
    
    s1 = School("黄埔军校")
    s1.show_attr()
    
    # ==== 执行结果 ==== Ps:可以看到并没有打印黄埔军校,说明拿的是School的 __dict__
    
    """
    ['学校类', '任意地方', '虚拟']
    ['学校类', '任意地方', '虚拟']
    """

     

    staticmethod

    作用


     

      静态方法只是名义上归属类管理,通过类和实例都可以调用,但这个方法既不和实例绑定也不和类绑定(既不拿类的__dict__也不拿实例的__dict__),因此它常常作为工具包一类的方法。

      通过@staticmethod语句,实现静态方法。

     

      Ps:有应用场景,静态方法不会和实例也不会和类绑定,就是一个普通的函数而已。那么为什么还要有这玩意儿?没有静态方法每次实例调用都会自动传入参数self,但是又不需要用到这个self,这就是资源上的浪费!如果将它做成@classmethod的话那么这个方法就只能拿到类的__dict__,这么做局限性太强。

     

      我们用静态方法实际上就是普通函数 + 类的封装特性。(类创建的局部命名空间不会与全局命名空间的函数产生冲突...)

     

    专属工具包静态方法案例


     

    class Foo(object):
    
        @staticmethod
        def tool(string):
            print("工具方法.",string)
    
    Foo.tool("类也可以调用")
    
    f1 = Foo()
    f1.tool("实例可以调用")
    
    print(Foo.tool)
    print(f1.tool)
    
    # ==== 执行结果 === Ps:可以看到,并没有变为实例绑定方法。因此也不会自动传入self
    
    """
    工具方法. 类也可以调用
    工具方法. 实例可以调用
    <function Foo.tool at 0x00000209FEEAFF70>
    <function Foo.tool at 0x00000209FEEAFF70>
    """ 

     

    小总结

     

      @property:将方法当做属性使用,另外还可以控制某个属性的增删改查期间发生的事儿。

      @classmethod:只会拿到类的__dict__,不会拿到实例的__dict__,因此也被叫做类的绑定方法,可以通过类调用,也可以通过实例调用。

      @staticmethod:不会拿类的__dict__,也不会拿实例的__dict__,因此常常被当做普通函数使用,可以通过类调用,也可以通过实例调用。

  • 相关阅读:
    OCP-1Z0-053-V12.02-235题
    OCP-1Z0-053-V12.02-524题
    OCP-1Z0-053-V12.02-525题
    OCP-1Z0-053-V12.02-526题
    OCP-1Z0-053-V12.02-535题
    OCP-1Z0-053-V12.02-540题
    OCP-1Z0-053-V12.02-617题
    OCP-1Z0-053-V12.02-649题
    如何制作Jar包并在android中调用jar包
    JAVA实现回调
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13058210.html
Copyright © 2011-2022 走看看