首页 > 编程语言 >Python的魔术方法,装饰器和属性

Python的魔术方法,装饰器和属性

时间:2023-05-07 15:12:23浏览次数:46  
标签:__ return name Python self 魔术 print def 属性

这里将介绍python的所谓魔法方法以及装饰器

魔术方法

一般在类中以双下划线包围的方法就是魔术方法,或者叫特殊方法。

简单来说,Python的魔术方法是为了利用Python的标准方法以及不用去记住标准操作的名称,实现更统一的接口。

image-20230507133421451

例如下面的代码

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                                        for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]


if __name__ == '__main__':
    print(len(deck))
    print(deck[0])

__len__这个特别方法使得调用len(beer_card)实际调用__len__

getitem 方法把 [] 操作交给了 self._cards 列表,所以我们的 deck 类自动支持切 片(slicing)操作。

输出如下

52
Card(rank='2', suit='spades')

另外,仅仅实现了 getitem 方法,对象就变成可迭代的了

for i in deck:
    print(i)

image-20230507134341143

同时__contains__可以实现in方法

除了上面通过特殊方法实现迭代,len(),切片等方法外,还可以实现类似重载运算符的效果。

from math import hypot 
class Vector:

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)

    def __abs__(self):
        return hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
v1 = Vector(3,4)
v2 = Vector(4,5)
v3 = v1+v2
print(v3)

输出Vector(7, 9)

还有__repr____str__

reprstr 的区别在于,后者是在 str() 函数被使用,或是在用 print 函数打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好。

如果你只想实现这两个特殊方法中的一个,repr 是更好的选择,因为如果一个对象没有 str 函数,而 Python 又需要调用它的时候,解释器会用 repr 作为替代。

  • {!r}就是使用format语法时候的%r。因此,我们只需要关注%r就好。
  • %r表示的用repr()处理;类似于的%s表示用str()处理一样

其他特别方法

image-20230507134927018

装饰器

装饰器的作用就是为已经存在的函数或对象添加额外的功能。
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def hello():
    print("hello")

hello()

装饰器涉及到闭包的概念,什么是闭包,一句话说就是,在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了

上述无参装饰器可以用于输出日志。

如果要在wrapper中访问参数,如下

def debug(func):
    def wrapper(*args, **kwargs):
        print("[DEBUG]: enter {}()".format(func.__name__))
        print("params", args, kwargs)
        return func(*args, **kwargs)

    return wrapper


@debug
def test(a,b):
    print("this is a test function")

如果要在装饰器中使用参数,还要在外面包围一层。

def logging(level):
    def outwrapper(func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(level, func.__name__))
            return func(*args, **kwargs)

        return wrapper

    return outwrapper


@logging(level="INFO")
def hello(a, b, c):
    print(a, b, c)

除了使用函数装饰器也可以是使用类装饰器

class logging(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("[DEBUG]: enter {}()".format(self.func.__name__))
        return self.func(*args, **kwargs)

@logging
def hello(a, b, c):
    print(a, b, c)

装饰器中使用参数

class logging(object):
    def __init__(self, level):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(self.level, func.__name__))
            return func(*args, **kwargs)
        return wrapper

@logging(level="TEST")
def hello(a, b, c):
    print(a, b, c)

属性

当我们创建一个类,以定义对象时,我们可能会希望一些属性对于外界是只读的,或者希望创建属性只能按特定的方式访问或修改。这时就可以使用 Python 中的属性(Property)。

在 Python 中,属性是包装在函数中的代码段,它们能够拦截对对象属性的访问和修改。Python 内置了@property 装饰器,可以用来修饰一个方法,使之成为属性调用。同时,Python 还提供了 @property 修饰器的对应方法的 setter 方法,用于设置属性。

简单来说,属性优化了之前使用公共方法来访问私有属性得方法同时有更精细的粒度。

class myObj:

    def __init__(self, name):
        self.__name = name
        print("init")

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

if __name__ == '__main__':
    obj = myObj("hello")
    print(obj.name)

输出

init
hello

如果使用obj.name = "world"更改属性则会报错.

添加

@name.setter
def name(self, newname):
     self.__name = newname

可以通过name属性更改self.__name

此外还有deleter

@name.deleter
def name(self):
     self.__name = None

使用del删除属性

del obj.name
print(obj.name)

输出就是None

参考资料

  1. Python常用魔术方法 - 知乎 (zhihu.com)
  2. 《流畅的Python》
  3. Python基础(十四)—装饰器 wrapper_luoz_python的博客-CSDN博客
  4. python 装饰器详解 - 知乎 (zhihu.com)
  5. Python @property属性详解 - 知乎 (zhihu.com)

标签:__,return,name,Python,self,魔术,print,def,属性
From: https://www.cnblogs.com/kanashiminoblog/p/17379346.html

相关文章

  • 软件测试|超好用超简单的Python GUI库——tkinter(十)
    前言上文我们介绍了tkinter的列表框处理,我们在日常生活中还会遇到组合框的情况,tkinter同样可以实现这个功能,下面我们来介绍一下tkinter如何实现组合框。Combobox控件上一篇文章,我们知道Listbox是一个供用户从列表项中选择相应条目的控件。但在有些情况下,比如列表的项目过多时,若使......
  • 分享Python采集50个jQuery代码,总有一款适合您
    Python采集的50个jQuery代码下载链接:https://pan.baidu.com/s/1KoCOk4lM-A8arAsn-apcMw?pwd=k3qo提取码:k3qo现代时尚的js消息通知插件时尚简洁的js轮播图特效插件jQuery文字翻转动画特效插件jQuery移动端下拉刷新、上拉加载更多插件jquery和CSS3半透明垂直Accordion特效基于TweenM......
  • 分享Python采集80个jQuery代码,总有一款适合您
    Python采集的80个jQuery代码下载链接:https://pan.baidu.com/s/1TeAqNtMgbrQyaF5cg6dt6A?pwd=d51f提取码:d51f基于HTML5SVG的炫酷进度条插件js全屏快速预览图片特效jquery滑动侧边栏插件jSidejs和CSS3图片360度全方位3D预览插件jQuery和CSS3滑动展开菜单按钮插件33种css3开关按钮特......
  • python asyncio
    例子importasyncioasyncdefmain():print("hello")awaitasyncio.sleep(1)print("world")asyncio.run(main())主要函数task=asyncio.create_tas()res=awaitasyncio.gather(task1,task2)#res:list获取返回值res=awaittask......
  • python的三大切换
    #1、窗口切换driver.switch_to.window()#2、iframe切换#方式一:通过iframe标签的name属性driver.switch_to.frame("login_frame")#方式二:先定位iframe的标签,再进行切换loc_ifr=(By.ID,"login_frame")iframe_ele=driver.find_element(*loc_ifr)driver.switch_to.fr......
  • 使用python rembg替换登记照背景方法
    参考材料:https://pypi.org/project/rembg/fromrembgimportremovefromPILimportImageinput_path='input.jpg'output_path='output.png'in_image=Image.open(input_path)no_bg_image=remove(in_image)#删除背景x,y=no_bg_image.si......
  • pip3 & python3 -m pip All In One
    pip3&python3-mpipAllInOne$sudopip3installpackage_name#等价于$sudopython3-mpipinstallpackage_name#-mmodule-name$sudopipinstallmath-package-xgqfrms$sudopip3installmath-package-xgqfrms#等价于$sudopython3-mpipinsta......
  • SLQ_C# DataAdapter数据适配器的4个属性
    DataAdapter数据适配器的4个属性:1.SelectCommand属性:向数据库发送查询SQL语句。2.DeleteCommand属性:向数据库发送删除SQL语句。3.InsertCommand属性:向数据库发送插入SQL语句。4.UpdateCommand属性:向数据库发送更新SQL语句。......
  • python3 xml.etree.ElementTree.ElementTree
    1、介绍对应整个xml结构。2、初始化classElementTree:def__init__(self,element=None,file=None):self._root=element#firstnodeiffile:self.parse(file)element,ElementTree.Element类型,即设置一个节点对象作为根节点file,str......
  • python3 xml etree使用
    1、创建xml(1)通过ElementTree.ElementTree类创建,并设置一个ElementTree.Element对象作为参数,该参数对象作为根节点(2)通过ElementTree.Element创建一个或多个节点,为这些节点设置tag、attrib、text和tail(3)这些节点通过父节点的append方法添加,管理关系。ElementTree.ElementTr......