python类方法中使用:修饰符@staticmethod和@classmethod的作用与区别,还有装饰器@property的使用

简介: python类方法中使用:修饰符@staticmethod和@classmethod的作用与区别,还有装饰器@property的使用

一、 @staticmethod(静态方法)和@classmethod(类方法)使用

1 @staticmethod和@classmethod使用说明:

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接通过类名就可以实现调用
使用直接类名.方法名()来调用。

这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。

2 @staticmethod和@classmethod的区别:

既然@staticmethod和@classmethod都可以直接类名.方法名()来调用,那他们有什么区别呢

从它们的使用上来看,

  • @staticmethod不需要表示自身对象的self和自身类的cls参数(这两个参数都不需要添加),就跟使用函数一样。
    使用:直接类名.属性名直接类名.方法名。 # 直接类名,也可以直接类名( )
  • @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
    使用:直接类名.属性名直接类名.方法名 # 直接类名,也可以直接类名( )

    :两者定义的装饰器调用方法一样,但是@classmethod装饰器定义的类方法需要传入类参数cls

如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。

3 @staticmethod和@classmethod的区别示例:

  1. @staticmethod示例:
    ```python

    直接定义一个test()函数

    def test():
    print "i am a normal method!"

定义一个类,其中包括一个类方法,采用@staticmethod修饰

class T:

@staticmethod
def static_test():   #没有self参数
    print "i am a static method!"

if name == "main":
test()
T.static_test()
T().static_test()

output:
i am a normal method!
i am a static method!
i am a static method!

2. @classmethod示例:
```python
class T:
    @classmethod
    def class_test(cls):     #必须有cls参数     #这里第一个参数是cls, 表示调用当前的类名
        print "i am a class method"

if __name__ == "__main__":
    T.class_test()
    T().class_test()

output:
i am a class method
i am a class method

4 小结:

定义一个类的静态方法,不需要self参数
定义一个类方法,需要cls参数

小结:在Python中类和实例都是对象,都占用了内存空间,合理的使用@staticmethod @classmethod方法,就可以不用实例化就直接使用类的方法啦

二、 property(特性)

1 什么是特性property

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

通俗的理解就是:用访问类属性的方式,直接调用类方法参考

import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2 #计算面积

    @property
    def perimeter(self):
        return 2*math.pi*self.radius #计算周长

c=Circle(10)
print(c.radius)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
314.1592653589793
62.83185307179586
'''

注意:此时的特性arear和perimeter不能被赋值

c.area=3 #为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''

设置属性值:

@property装饰的方法是获取属性值的方法,被装饰方法的名字会被用做属性名。
@属性名.setter 装饰的方法是设置属性值的方法。
@属性名.deleter装饰的方法是删除属性值的方法。

属性名要和上面property装饰的方法名保持一致(参考):

class Student:

    def __init__(self):
        self._score = ''
    @property
    def score(self):
        return self._score
    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('分数必须是数字')
        if value > 100 or value < 0:
            raise ValueError('分数不符实际')
        self._score = value
    @score.deleter
    def score(self):
        del self._score


s = Student()
s.score = 100
print(s.score)  # 100
s.score = 150
print(s.score)  # 报错
del s.score
print(s.score)  # 报错

2 为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

除此之外,看下

ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

class Foo:
    def __init__(self,val):
        self.__NAME=val #将所有的数据属性都隐藏起来

    @property
    def name(self):
        return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)

    @name.setter
    def name(self,value):
        if not isinstance(value,str):  #在设定值之前进行类型检查
            raise TypeError('%s must be str' %value)
        self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter
    def name(self):
        raise TypeError('Can not delete')

f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'

@property 一般会在什么场景下使用呢,因为它会把类方法当作类属性进行调用,因此一般我们需要获取返回值,而且会在调用属性(方法)中做一定的处理:

比如,我们获取路径文件的名的后缀

class Foo:
    def __init__(self):
        self.name = "Python"

    @property
    def get_name(self):
        return self.name

obj = Foo()
name = obj.name
name = obj.get_name

# 上面的这种情况,我们就没有必要把该方法再设置成属性了,因为在构造函数中也可以直接获取了
import os

class Foo:
    def __init__(self,path):
        self.path = path

    @property
    def get_file_suffix(self):
        filename = os.path.basename(self.path)
        suffix = filename.split('.')[-1]
        return suffix

obj = Foo('/test/test.txt')
name = obj.get_name
# 上面的这种情况,我们就可以把方法设置成属性,因为我们在方法内还进行了一些操作处理,有些内部操作可能更复杂,但是通过属性就可以直接获取到了

当然上面的写法,也可以不使用@property把方法定义成属性,而是在构造函数中直接调用

import os

class Foo:
    def __init__(self,path):
        self.path = path
        self.suffix = self.get_file_suffix()

    def get_file_suffix(self):
        filename = os.path.basename(self.path)
        suffix = filename.split('.')[-1]
        return suffix

obj = Foo('/test/test.txt')
name = obj.suffix

但是上面这种写法有一个问题,当我们实例化对象的时候,它就会自动先在构造函数中调用了一次get_file_suffix()这个函数,此时我们还没有主动让实例化的对象去调用suffix这个属性,这显然不是我们想要的效果,此时你对@property的用法也有了更深一点的认识了吧!

目录
相关文章
|
14天前
|
开发者 Python
探索Python中的装饰器:从基础到高级应用
本文将带你深入了解Python中的装饰器,这一强大而灵活的工具。我们将一起探讨装饰器的基本概念,它们如何工作,以及如何使用它们来增强函数和类的功能,同时不改变其核心逻辑。通过具体代码示例,我们将展示装饰器的创建和使用,并探索一些高级应用,比如装饰器堆栈和装饰带参数的装饰器。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角,帮助你更有效地使用装饰器来简化和优化你的代码。
|
3天前
|
缓存 数据安全/隐私保护 Python
python装饰器底层原理
Python装饰器是一个强大的工具,可以在不修改原始函数代码的情况下,动态地增加功能。理解装饰器的底层原理,包括函数是对象、闭包和高阶函数,可以帮助我们更好地使用和编写装饰器。无论是用于日志记录、权限验证还是缓存,装饰器都可以显著提高代码的可维护性和复用性。
18 5
|
14天前
|
测试技术 开发者 Python
探索Python中的装饰器:从入门到实践
装饰器,在Python中是一块强大的语法糖,它允许我们在不修改原函数代码的情况下增加额外的功能。本文将通过简单易懂的语言和实例,带你一步步了解装饰器的基本概念、使用方法以及如何自定义装饰器。我们还将探讨装饰器在实战中的应用,让你能够在实际编程中灵活运用这一技术。
34 7
|
13天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
14天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
41 6
|
13天前
|
存储 缓存 Python
Python中的装饰器深度解析与实践
在Python的世界里,装饰器如同一位神秘的魔法师,它拥有改变函数行为的能力。本文将揭开装饰器的神秘面纱,通过直观的代码示例,引导你理解其工作原理,并掌握如何在实际项目中灵活运用这一强大的工具。从基础到进阶,我们将一起探索装饰器的魅力所在。
|
14天前
|
测试技术 开发者 Python
深入理解Python装饰器:从基础到高级应用
本文旨在为读者提供一个全面的Python装饰器指南,从其基本概念讲起,逐步深入探讨其高级应用。我们将通过实例解析装饰器的工作原理,并展示如何利用它们来增强函数功能、控制程序流程以及实现代码的模块化。无论你是Python初学者还是经验丰富的开发者,本文都将为你提供宝贵的见解和实用的技巧,帮助你更好地掌握这一强大的语言特性。
27 4
|
14天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
13天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
1天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
95 80