lesson 041 —— 静态属性

lesson 041 —— 静态属性

静态属性

我们知道类既有函数属性又有数据属性,实例只有数据属性,我们在使用实例调用类的函数属性并运行时,总要带上函数后面的括号才能运行,不然总是调用函数的内存地址。那么我们如何能像调用数据属性一样调用函数属性呢?

类中提供了 @property 关键字,可以看成 @property 是一个装饰器,装饰器的作用是调用类的函数属性 key 值时,直接来运行该 key 值对应的函数。像是调用类的属性一样来直接调用并运行类的函数。

注意: 当类中的函数有其他参数时(非 self ),加上 @property 关键字会报错,提示缺少必要的位置参数。可以判断,@property的作用是:直接运行被装饰的函数,不能带参数。

class Door:
    address = "地球"

    def __init__(self,size,color,type):#构造函数
        self.size = size
        self.color = color
        self.type = type

    @property
    def open(self):
        "门打开的方法"
        print("这个%s门打开了" %self.type)

    @property
    def off(self,time):
        "门关闭的方法"
        print("这个%s门关闭了,时间为;%d" %(self.type,time))

door1 = Door(16, 'red', '木门')

#调用数据属性
print(door1.size)
print(door1.address)

#调用函数属性
# door1.open()    #函数后面的括号每次都必须要带上

#实例调用类的静态属性
print(Door.__dict__)
door1.open
#door1.off   # 报错,提示缺少一个参数time
#door1.off(30)   # 报错

结果

16
地球
{'__module__': '__main__', 'address': '地球', '__init__': <function Door.__init__ at 0x7f5d6d43cbf8>, 'open': <property object at 0x7f5d6d4e31d8>, 'off': <property object at 0x7f5d6d4e33b8>, '__dict__': <attribute '__dict__' of 'Door' objects>, '__weakref__': <attribute '__weakref__' of 'Door' objects>, '__doc__': None}
这个木门门打开了12

类方法

如果要求,不进行实例化,直接调用类的函数,此时会提示缺少必要的位置参数self。

class Door:
    address = "地球"

    def __init__(self,size,color,type):#构造函数
        self.size = size
        self.color = color
        self.type = type

    def open(self):
        "门打开的方法"
        print("这个%s 生产的门打开了" %self.address)

    def off(self,time):
        "门关闭的方法"
        print("这个%s 生产的门关闭了,时间为;%s" %(self.address,time))

# 不传参数调用
Door.open()   # 报错,提示说缺少参数 self

# 随意传一个参数调用
Door.open('山东') # 报错,提示说 str 类没有 addess 的属性

我们加上参数后,仍然报错。虽然我们可以随意加上位置参数,但是注意到此处的 self 有特殊含义,它是指实例的本身,也就是说要使用 self 必须要先实例化才行。为了解决这个问题,我们引入另一个 @classmethod 装饰器后,就可以直接通过类来调用类的函数属性了(该函数带类的数据属性参数),如下所示:

class Door:
    address = "地球"

    def __init__(self,size,color,type):#构造函数
        self.size = size
        self.color = color
        self.type = type

    @classmethod
    def open(cls):
        # cls 是 Python 推荐的形参
        "门打开的方法"
        print("这个%s 生产的门打开了" %cls.address)
        cls.off(cls, 20)   # 这个是把类作为参数传进去了

    def off(self,time):
        "门关闭的方法"
        print("这个%s 生产的门关闭了,时间为;%s" %(self.address,time))

Door.open()

# 对象调用类方法
d1 = Door(16, 'red', 'wood')
d1.open()

# 结果
这个地球 生产的门打开了
这个地球 生产的门关闭了,时间为;20
这个地球 生产的门打开了
这个地球 生产的门关闭了,时间为;20

注意: 类方法与对象的属相没有关系,虽然对象可以调用类方法,但是,类方法里面使用的,都是类的属性,与对象属性没有关系。

静态方法

如果要求: 在类中定义一个函数,要求该函数中的位置函数与实例无关,与所在的类本身也无关。为了解决该问题,现引入了 @staticmethod

class Door:
    address = "地球"
    
    def __init__(self,size,color,type):#构造函数
        self.size = size
        self.color = color
        self.type = type
        
    def open(self):
        print("这个%s门打开了" %self.type)
        
    def off(self,time):
        print("这个%s门关闭了,时间为;%s" %(self.type,time))
        
    @staticmethod
    def test(x,y):
        print("%s,%s的乘积为:%s"%(x,y,x*y))

    def test1(x,y):
        print("%s,%s的乘积为:%s"%(x,y,x*y))

door1 = Door(16, 'red', '木门')

#调用静态方法test
Door.test(1,3)
door1.test(2,5)

#调用常规方法test1
Door.test1(1,3)
door1.test1(2,5)    # 报错,说只有两个参数,但是传进来了三个参数

可以看出,虽然 test 方法与实例无关,与类本身也无关,但是却可以通过实例和类来调用它,却使用实例调用它是不会传入实例本身的位置参数(在正常类方法中,实例化类后,实例在调用它时,会自动默认首先传入实例本身即 self )。

**为什么不能直接在类中定义一个函数,不传 self 形参?按照上面的提议是否能满足实例可以调用,类本身也可以调用的要求呢?**原因很简单,self 只是一个形参,和一般函数形参一样,只是约定成俗的使用 self,使用其它的形参也是可以的。

我们可以看出,如果直接在类中定义一个常规方法(不含self的形参),通过类本身访问它,但是通过实例来访问它时虽然也是传入2个参数,但是实际行python自动默认首位传入了self,这样就造成了上面的情况了(传的是2个参数,收到的是3个参数)

注意: 静态方法中不能调类属性和方法,也不能调用实例变量,只是类的工具包。因为没有self,也就不能指类本身或实例本身,从而不能调用相应的类属性和类方法。

你可能感兴趣的:(Python,python)