首页 > 编程语言 >第二十二天python3 classmethod、staticmethod、property装饰器学习笔记

第二十二天python3 classmethod、staticmethod、property装饰器学习笔记

时间:2023-02-10 00:00:59浏览次数:41  
标签:__ classmethod self staticmethod ._ property age def cls

classmethod

1、在类定义中,使用@classmethod装饰器修饰的方法;

2、必须至少有一个参数,且第一个参数留给了cls,cls指代调用者即类对象自身;

3、cls这个标识符可以是任意合法名称,但是为了易读,不要修改;

4、通过cls可以直接操作类的属性;但是无法通过cls操作类的实例,因为有类的时候未必有实例,就算有实例,一个类可以有多个实例,并不能确定操作哪个实例;

class Person:
    def __init__(self):
        print(id(self),"这是self的ID")
    
    @classmethod
    def people(cls):
        print(id(cls()), "这是cls()的ID")

Person.people()  # 这属于类方法调用,如果classmethod发现是类方法,则将类传递进去作为参数,也就是people(cls)。
print("######")
Person().people()  # 这属于实例方法调用,如果classmethod发现是实例方法,则将实例的类传递进去。
"""执行结果:

1238665306800 这是self的ID
1238665306800 这是cls()的ID
######
1238665306800 这是self的ID
1238665306800 这是self的ID
1238665306800 这是cls()的ID

"""

  根据上述代码可知:cls的本质就是一个类,也就是上面代码的Person类本身。cls()和self都是类的实例也就是类对象,所以他们ID相同。classmethod所装饰的方法被称为类方法,因此第一个传进来的参数就不是self了,而是class类。

  那么classmethod能做什么呢?1、可以修改类属性的值。2、产生类的实例

1、修改类属性的值

class Person:
    ID = 0
    def __init__(self,name):
        self.name = name
    
    @classmethod
    def people(cls,age):
        cls.ID += age
        return cls.ID

P = Person('zhang')
print(P.people(18))
print(Person.__dict__)

"""执行结果:
18
{'__module__': '__main__', 'ID': 18, '__init__': <function Person.__init__ at 0x0000021CE8068C10>, 'people': <classmethod object at 0x0000021CE800A5B0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
"""

  从上述代码中可知:Person类的默认属性ID的值为0,可以通过传值的方式将ID的默认值修改。同时也能在Person类的属性列表中看到。

2、产生类的实例

"""1675847343.624 0.001 192.168.80.89 - 204 0 POST http://gitlab.test.com/api/v4/jobs/request - NONE/127.0.0.1:8099"""
class Log:
    def __init__(self,time,request_time,remote_addr,x_forword_f,status,body_bytes,method,url,remote_user,upstream_addr):
        self.time = time
        self.request_time = request_time
        self.remote_addr = remote_addr
        self.x_forword_f = x_forword_f
        self.status = status
        self.body_bytes = body_bytes
        self.method = method
        self.url = url
        self.remote_user = remote_user
        self.upstream_addr = upstream_addr
    
    @classmethod
    def analysis(cls,data):
        time,request_time,remote_addr,x_forword_f,status,body_bytes,method,url,remote_user,upstream_addr = data.split(" ")
        return cls(time,request_time,remote_addr,x_forword_f,status,body_bytes,method,url,remote_user,upstream_addr)

L = "1675847343.624 0.001 192.168.80.89 - 204 0 POST http://gitlab.test.com/api/v4/jobs/request - NONE/127.0.0.1:8099"
A = Log.analysis(L)
print(A.time,A.method,A.url)

  上述代码中,通过切割日志,将值传递给cls(),生成类的实例,然后就可以按需获取所需要的字段。

staticmethod

1、在类定义中,使用@staticmethod装饰器修饰的方法;

2、调用时,不会隐式传入参数,静态方法只是表明这个方法属于这个名词空间,和函数归在一起,方便组织管理;

import datetime
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    
    @staticmethod
    def dtime():
        nowtime = datetime.datetime.now()
        return nowtime

print(Person.dtime())
print(Person('zhang',18).dtime())
print(Person.__dict__)

  静态方法比较简单,功能也相对单一,可以作为类的额外功能,在不用传入self或者cls的情况下,可以读取文件或者记录日期之类的功能。

property

1、一般好的设计是:把实例的属性保护起来,不让外部直接访问,外部使用getter(隐式传入)读取属性和setter方法设置属性;

2、用property装饰器生成的属性称为只读属性;property可以单独存在;

3、property装饰器必须在前,setter,deleter装饰器在后;

4、property装饰器能通过简单的方式,把对方法的操作变成对属性的访问,也就是将函数的返回值作为类的属性,调用这个被装饰的函数不需要去加括号运行,而是直接像调用类属性一样获取值。

5、加了setter装饰器之后就是可读可写属性;且接收2个参数,第一个是self,第二个是将要赋值的值;但是setter不能单独存在;

6、删除函数基本不用;

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    
    @property
    def per_age(self):    # 只读属性
        return self.age
    @per_age.setter    # 给属性增加修改属性
    def per_age(self,age):
        self.age = age
    @per_age.deleter
    def per_age(self):  # del的功能取决于你自己在这里设置的操作
        print('del age')
        self.age = None 

P = Person('zhang',18)  # 在P.per_age被注释的情况下,打印的结果是18。

# P.per_age = 30  # 在该句取消注释的情况下,在类外部重新定义了per_age属性的返回值。
print(P.per_age)

del P.per_age  # 返回del功能内所做的操作的返回值。
print(P.per_age)

实现温度间的转换

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

"""
℃ = 5 x (℉ - 32) / 9  摄氏度
℉ = 9 x ℃ / 5 + 32  华氏度
K = ℃ + 273.15  开氏温度
"""
class Temperature:
    def __init__(self,num,unit="c"):
        self._c = None
        self._f = None
        self._k = None
        if unit == "f":
            self._f = num
            self._c = self.f2c(num)
            self._k = self.f2k(num)
        elif unit == "k":
            self._k = num
            self._c = self.k2c(num)
            self._f = self.k2f(num)
        else:
            self._c = num
            self._f = self.c2f(num)
            self._k = self.c2k(num)       

    @property
    def c(self):
        return self._c
    @property
    def f(self):
        if self._f is None:
            self._f = self.c2f(self._c)
        return self._f
    @property
    def k(self):
        if self._k is None:
            self._k = self.c2k(self._c)
        return self._k

    @classmethod
    def c2f(cls,c):
        return 9 * c/5 + 32
    @classmethod
    def c2k(cls,c):
        return c + 273.15
    @classmethod
    def f2c(cls,f):
        return 5 * (f - 32) / 9
    @classmethod
    def f2k(cls,f):
        return cls.f2c(f) + 273.15
    @classmethod
    def k2c(cls,k):
        return k - 273.15
    @classmethod
    def k2f(cls,k):
        return 9 * cls.k2c(k) / 5 + 32

# 示例:开氏温度转华氏温度
t = Temperature(100,"k")
print(t.f)

 

标签:__,classmethod,self,staticmethod,._,property,age,def,cls
From: https://www.cnblogs.com/zhangzhide/p/17103092.html

相关文章