Python magic methods, decorators and attributes


title: Special methods and decorators for python author: Sekyoro date: 2023-05-07 11:31:24 tags: - python categories: archives: password: abstract: message:

Here will introduce the so-called magic method and decorator of python

magic method

Generally, methods surrounded by double underscores in a class are magic methods, or special methods.

In simple terms, Python's magic method is to take advantage of Python's standard methods and avoid having to remember the names of standard operations to achieve a more uniform interface.

image-20230507133421451
image-20230507133421451

For example the following code

import collections

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

class FrenchDeck:
    ranks = [str(n) for n in range(211)] + 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__This particular method makes calling len(beer_card) actually call__len__

The getitem method offloads the [] operation to the self._cards list, so our deck class automatically supports slicing.

The output is as follows

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

In addition, only by implementing the getitem method, the object becomes iterable

for i in deck:
    print(i)
image-20230507134341143
image-20230507134341143

At the same time __contains__it is possible to implement inthe method

In addition to implementing iteration, len(), slicing and other methods through special methods above, effects similar to overloaded operators can also be achieved.

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)

Output Vector(7, 9)

and __repr_____str__

The difference between repr and str is that the latter is called when the str() function is used, or when an object is printed with the print function, and the string it returns is more friendly to the end user.

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

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

其他特别方法

image-20230507134927018
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)。

In Python, properties are pieces of code wrapped in functions that intercept access to and modification of properties of an object. Python has a built-in @property decorator that can be used to decorate a method to make it a property call. At the same time, Python also provides the setter method of the corresponding method of the @property decorator, which is used to set the property.

In simple terms, properties optimize the way that previously used public methods to access private properties while having a finer granularity.

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)

output

init
hello

An error will be reported if obj.name = "world"the property is changed.

Add to

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

Can be changed through the name attributeself.__name

In addition there is deleter

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

Use del to delete attributes

del obj.name
print(obj.name)

output isNone

References

  1. Magic methods commonly used in Python - Zhihu (zhihu.com)
  2. "Smooth Python"
  3. Python Basics (14) - Decorator wrapper_luoz_python's Blog - CSDN Blog
  4. Detailed explanation of python decorators - Zhihu (zhihu.com)
  5. Detailed explanation of Python @property attributes - Zhihu (zhihu.com)

This article is published by mdnice multi-platform

Guess you like

Origin blog.csdn.net/aqwca/article/details/130542916