Python中的属性(字段)、方法和特性(装饰器)

Python中的属性(字段)、方法和特性(装饰器)

类属性和实例属性

类属性:类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本。对于公有的类属性,在类外可以通过类对象和实例对象访问。

实例属性:实例属性就是实例对象所拥有的属性。

class People(object):
    country = 'name' #类属性

print(People.country)
p = People()   # 创建一个实例对象
print(p.country)
p.country = 'xiaoke' 
print(p.country)      #实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country    #删除实例属性
print(p.country)
name
name
xiaoke
name
name

小结

  • 如果需要在类外修改类属性,必须通过实例对象去调用类方法中设置属性方法进行修改。

  • 如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

  • 但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。

类方法、实例方法和静态方法

类方法

类方法是类对象所拥有的方法,需要用装饰器"@classmethod"来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以"cls"作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。

class People:
    country = "China"
    
#     类方法
    @classmethod
    def getCountry(cls):
        return cls.country
    
p = People()
print(People.getCountry())
print(p.getCountry())
China
China

类方法还有一个用途就是可以对类属性进行修改。

class People:  
    country = 'china'  
      
    #类方法,用classmethod来进行修饰  
    @classmethod  
    def getCountry(cls):  
        return cls.country  
         
    @classmethod  
    def setCountry(cls,country):  
        cls.country = country  
          
  
p = People()  
print(p.getCountry())    #可以用实例对象引用  
print(People.getCountry())    #可以用类对象引用  
  
p.setCountry('japan')     
  
print(p.getCountry())     
print(People.getCountry()) 
china
china
japan
japan

实例方法

实例方法在类中最常定义的成员方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以名为’self’的变量作为第一个参数(当然可以以其他名称的变量作为第一个参数)。在类外实例方法只能通过实例对象去调用,不能通过其他方式去调用。

class People:  
    country = 'China'  
      
    #实例方法  
    def getCountry(self):  
        return self.country  
    
    
          
  
p = People() 
# p.country = "Japan"
print(p.getCountry())         #正确,可以用过实例对象引用  
print(People.getCountry())    #错误,不能通过类对象引用实例方法 
China



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-6-cb0faf0872a3> in <module>()
     12 # p.country = "Japan"
     13 print(p.getCountry())         #正确,可以用过实例对象引用
---> 14 print(People.getCountry())    #错误,不能通过类对象引用实例方法


TypeError: getCountry() missing 1 required positional argument: 'self'

静态方法

静态方法需要通过修饰器"@staticmethod"来进行修饰,静态方法不需要多定义参数。

class People:  
    country = 'China'  
    
#     静态方法 
    @staticmethod   
    def getCountry():  
        return People.country  
            
print(People.getCountry())#可以用类对象引用
p = People()
print(p.getCountry())#可以用实例对象引用
China
China

小结

对于类属性和实例属性,如果在类方法中引用某个属性,该属性必定是类属性;而如果在实例方法中引用某个属性(不作更改),并且存在同名的类属性,此时若实例对象有该名称的实例属性,则实例属性会屏蔽类属性,即引用的是实例属性,若实例对象没有该名称的实例属性,则引用的是类属性;如果在实例方法更改某个属性,并且存在同名的类属性,此时若实例对象有该名称的实例属性,则修改的是实例属性,若实例对象没有该名称的实例属性,则会创建一个同名称的实例属性。
想要修改类属性,如果在类外,可以通过类对象修改,如果在类里面,只有在类方法中进行修改。

从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用。
类对象可以访问类方法,不可以访问实例方法;实例对象可以访问类方法,也可以访问实例方法。

特性:@property装饰器

Python内置的@property装饰器,就是负责把类方法变成只读属性调用的。这种把方法变属性,就是特性。既能检查参数,又可以用类似属性这样简单的方式来访问类的变量。

class Student(object):

    # 只读,类似于get方法
    @property
    def Att(self):
        return self._score

    # 只写,类似于set方法
    @Att.setter
    def Att(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.Att = 88 # OK,实际转化为s.set_score(60)
print(s.Att) # OK,实际转化为s.get_score()

s.Att = 999999#只接抛出异常了,异常如下:

# ValueError: score must between 0 ~ 100!
88



---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-9-b5dcf8a6f9e9> in <module>()
     19 print(s.Att) # OK,实际转化为s.get_score()
     20 
---> 21 s.Att = 999999#只接抛出异常了,异常如下:
     22 
     23 # ValueError: score must between 0 ~ 100!


<ipython-input-9-b5dcf8a6f9e9> in Att(self, value)
     12             raise ValueError('score must be an integer!')
     13         if value < 0 or value > 100:
---> 14             raise ValueError('score must between 0 ~ 100!')
     15         self._score = value
     16 


ValueError: score must between 0 ~ 100!

装饰器是在代码运行期间动态增加函数功能的方式,本质上就是一个返回函数的高阶函数。一个完整的decorator写法如下:

import functools

# 不带参数2层嵌套实现
def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2015-3-25')
    
now()
call now():
2015-3-25
import functools

# 带参数三层嵌套实现
def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log("execute")
def now():
    print('2015-3-25')
    
now()
execute now():
2015-3-25

示例:设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间。

import time, functools

def metric(fn):
    @functools.wraps(fn)
    def wrapper (*args,**kw):
        start=time.time()
        result=fn(*args,*kw)
        end=time.time()
        print('%s is executed %s ms' %(fn.__name__, (end-start)*1000))
        return result
    return wrapper


# 测试
@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y;

@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z;

f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')
fast is executed 1.9998550415039062 ms
slow is executed 124.0072250366211 ms

小结

在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。

decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
回答: Python属性装饰器是一种用于修改或扩展属性的工具。属性装饰器可以在定义属性时使用,通过在属性定义前使用@符号,将装饰器应用于属性。常见的属性装饰器有@classmethod、@staticmethod和@property。 @classmethod装饰器用于定义方法方法可以通过本身调用,也可以通过实例调用。方法的第一个参数通常是cls,表示本身。 @staticmethod装饰器用于定义静态方法静态方法不需要访问实例属性,因此不需要传递实例作为参数。 @property装饰器用于定义属性的getter方法,可以通过实例直接访问属性,而不需要调用方法。同时,@property还可以定义属性的setter方法,用于设置属性的值。 除了这些内置的属性装饰器,还可以自定义属性装饰器。自定义属性装饰器可以通过定义一个,并实现__get__、__set__和__delete__方法来实现对属性的访问、设置和删除的控制。 属性装饰器Python的应用非常广泛,可以用于增加属性的验证、缓存、延迟加载等功能,提高代码的可读性和灵活性。 #### 引用[.reference_title] - *1* [python装饰器详解](https://blog.csdn.net/weixin_44992737/article/details/125868592)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Python装饰器详解](https://blog.csdn.net/qq_62789540/article/details/124513178)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森森向上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值