# 27. 对象、类方法、静态方法


# 属性

属性:将一个方法(函数)伪装成一个属性,在代码的级别上并没有本质的提升,但是可以让代码能够变得更合理

伪装后的属性也能拥有正常属性的删改查,但是需要我们做一些代码操作


# 属性初始 - 属性三部曲

有什么地方需要呢,一般来说在静态变量是不能赋值动态运算跟动态代码的,这时就可以用一个方法来接收,在用属性伪装来属性, 调用就跟正常的静态变量差不多

@property  # 可以把方法伪装成属性
@方法名.setter  # 修改,可以让方法类似于属性一样拥有修改功能,简单来说就是一旦执行修改操作,Python会默认定位执行setter下的方法
@方法名.deleter  #删除,可以让方法类似于属性一样拥有删除功能,简单来说就是一旦执行删除操作,Python会默认定位执行deleter下的方法

# 来一个简单的伪装属性 - (@property)

计算人体的BMT值,算法:体重(kg)÷身高^2(m)

class Steward:
    def __init__(self,name,weight,height):
        print("小服务系统目前只支持计算BMT值")
        self.name = name
        self.__weight = weight
        self.__height = height

    @property
    def BMT(self):
        print("您的BMI值:%s ,请注意保重身体,小凡的服务到此结束。。。。。。" % (self.__weight/self.__height**2))
        print("""
        成人的BMI数值:
            过轻:低于18.5
            正常:18.5-23.9
            过重:24-27
            肥胖:28-32
            非常肥胖, 高于32
        """)
weight = input("请输入您的体重(kg):")
height = input("请输入您的身高(M):")
s1 = Steward("江凡",int(weight),float(height))
s1.BMT

​ 以上程序,整体设为小服务系统,肯定不止只有一个BMT运算服务,所以BMT运算服务需要用一个方法来实现,这样子 需要调用BMT这方法就需要调用方法一样,这样子不行,加上@property,就可以把方法伪装成为属性,这样子这个方 法要想被调用,就只能通过类似调用属性的代码去调用他


# 属性拥有修改功能 - (@方法名.setter)

class age:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    @property
    def age(self):
        print(self.__age)

    @age.setter
    def age(self,age):
        self.__age = age

a1 = age("江凡",22)
a1.age
a1.age = "12"
a1.age

​ 通过@age.setter,会发现,伪装的属性可以被修改,不过这样的修改还很基础,不够完善

class age:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    @property
    def age(self):
        print(self.__age)

    @age.setter
    def age(self,age):
        if type(age) is int:
            self.__age = age
        else:
            print("输入的数据,数据类型不是int类型")


a1 = age("江凡",22)
a1.age
a1.age = 12
a1.age

​ 上面的代码,修改方法部分加了一点判断,判断想更新的数值是不是int类型的


# 属性拥有删除功能 - (@方法名.deleter)

class age:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    @property
    def age(self):
        print(self.__age)

    @age.setter
    def age(self,age):
        if type(age) is int:
            self.__age = age
        else:
            print("输入的数据,数据类型不是int类型")

    @age.deleter
    def age(self):
        del self.__age

a1 = age("江凡",22)
del a1.age
a1.age


# 类方法

类方法:通过类名调用的方法,类方法中第一个参数名称跟普通方法的self一样,有个名称(cls),在调用类方法的时候,Python会自动将类空间地址传给cls

class a:

    @classmethod
    def so(cls):
        print(cls)
        
a.so()

执行结果:
<class '__main__.a'>

# 类方法的应用场景 - 类方法三部曲


# 类中方法没有对象参与的类

在类中有些方法不需要对象参与的就可以使用类方法

class a:
    name = "江凡"
    age = "22"

    @classmethod
    def so(cls):
        print("姓名:%s ,年龄:%s" %(cls.name,cls.age))

a.so()

​ 以上实例,在不用实例化的情况下,可以使用类方法


# 对类中的静态变量进行修改用类方法

如果需要对类中的静态变量进行修改的话,也可以使用类方法

class a:
    name = "江凡"
    age = "22"

    @classmethod
    def so(cls):
        cls.name = "江先生"
        print(cls.name)

a.so()
print(a.name)

执行结果:
江先生
江先生

# 继承中,父类得到子类的类空间

在继承中,如果想要父类能调用子类的类空间一切对象的话,就可以使用类方法

class a:
    @classmethod
    def so(cls):
        print("姓名:%s ,年龄:%s" %(cls.name,cls.age))

class b(a):
    name = "江凡"
    age = "22"

b.so()

执行结果:
姓名:江凡 ,年龄:22

​ 在以上实例中,执行b.so(),子类中没有,去父类找,父类有,父类中的cls参数是子类的类空间地址



# 静态方法

静态方法跟直接外面写函数没有什么区别,但是最大的区别就是归类

可以提升代码的复用性,能增加代码的清晰度

class so:
    @staticmethod
    def a():
        print("这是一个静态方法")

    @staticmethod
    def b():
        print("这是一个静态方法")

    @staticmethod
    def c():
        print("这是一个静态方法")

so.a()
so.b()
so.c()

执行结果:
这是一个静态方法
这是一个静态方法
这是一个静态方法

​ 以上实例,静态方法可以用于归类存放,把功能或作用差不多的归类到一个类中

class str(object):
    """
    str(object='') -> str
    str(bytes_or_buffer[, encoding[, errors]]) -> str
    
    Create a new string object from the given object. If encoding or
    errors is specified, then the object must expose a data buffer
    that will be decoded using the given encoding and error handler.
    Otherwise, returns the result of object.__str__() (if defined)
    or repr(object).
    encoding defaults to sys.getdefaultencoding().
    errors defaults to 'strict'.
    """
    def capitalize(self): # real signature unknown; restored from __doc__
        """
        S.capitalize() -> str
        
        Return a capitalized version of S, i.e. make the first character
        have upper case and the rest lower case.
        """
        return ""

    def casefold(self): # real signature unknown; restored from __doc__
        """
        S.casefold() -> str
。。。。。。
。。。。。。
。。。。。。

​ 以上实例,上面代码是从str的详细文档中获取一小部分的,但是大概可以看出,str是一个主类,下面分部的都是str的 功能,从这样也可以看出来,有效的分类归类可以明显的提高代码的可读性