什么是;at";(@)符号在Python中是什么?

什么是;at";(@)符号在Python中是什么?,python,syntax,python-decorators,Python,Syntax,Python Decorators,我正在看一些使用@符号的Python代码,但我不知道它是做什么的。我也不知道该搜索什么,因为搜索Python文档时,Google不会返回相关结果,如果包含@符号。它表示您正在使用装饰程序。这是从2008年开始的。行开头的@符号用于类、函数和方法装饰器 请在此处阅读更多信息: 您将遇到的最常见的Python装饰程序有: 如果你在一行中看到一个 @ /代码>,那就不同了,矩阵乘法。 此代码段: def decorator(func): return func @decorator

我正在看一些使用
@
符号的Python代码,但我不知道它是做什么的。我也不知道该搜索什么,因为搜索Python文档时,Google不会返回相关结果,如果包含
@
符号。

它表示您正在使用装饰程序。这是从2008年开始的。

行开头的
@
符号用于类、函数和方法装饰器

请在此处阅读更多信息:

您将遇到的最常见的Python装饰程序有:

如果你在一行中看到一个<代码> @ /代码>,那就不同了,矩阵乘法。 此代码段:

def decorator(func):
   return func

@decorator
def some_func():
    pass
等同于此代码:

def decorator(func):
    return func

def some_func():
    pass

some_func = decorator(some_func)
在decorator的定义中,您可以添加一些函数通常不会返回的修改内容。

示例 这表明
函数
/
方法
/
基本上是在
@
符号之后,作为
参数
传递给
函数
/
方法

首次见到 微框架烧瓶从一开始就以以下格式引入了装饰器

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"
这反过来又转化为:

rule      = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    pass

意识到这一点,我终于对Flask感到心平气和。

用另一种方式告诉别人:是的,它是一个装饰师

在Python中,它类似于:

  • 创建函数(在@call下面)
  • 调用另一个函数对创建的函数进行操作。这将返回一个新函数。您调用的函数是@的参数
  • 用返回的新函数替换定义的函数

  • 这可以用于各种有用的东西,因为函数是对象,只是必要的指令。

    在Python 3.5中,您可以作为运算符重载
    @
    。它被命名为
    \uuuu matmul\uuuu
    ,因为它被设计用来进行矩阵乘法,但它可以是您想要的任何东西。有关详细信息,请参阅

    这是矩阵乘法的一个简单实现

    class Mat(list):
        def __matmul__(self, B):
            A = self
            return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                        for j in range(len(B[0])) ] for i in range(len(A))])
    
    A = Mat([[1,3],[7,5]])
    B = Mat([[6,8],[4,2]])
    
    print(A @ B)
    
    此代码生成:

    [[18, 14], [62, 66]]
    

    从Python 3.5开始,@'被用作矩阵乘法的专用中缀符号(PEP 0465——请参见)

    在Python中,“at”(@)符号做什么? 简而言之,它用于修饰语法和矩阵乘法

    class Mat(list):
        def __matmul__(self, B):
            A = self
            return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                        for j in range(len(B[0])) ] for i in range(len(A))])
    
    A = Mat([[1,3],[7,5]])
    B = Mat([[6,8],[4,2]])
    
    print(A @ B)
    
    在装饰器的上下文中,以下语法:

    @decorator
    def decorated_function():
        """this function is decorated"""
    
    a @ b
    
    相当于:

    def decorated_function():
        """this function is decorated"""
    
    decorated_function = decorator(decorated_function)
    
    在矩阵乘法的上下文中,
    a@b
    调用
    a.\uuu matmul\uuuu(b)
    -使用以下语法:

    @decorator
    def decorated_function():
        """this function is decorated"""
    
    a @ b
    
    相当于

    dot(a, b)
    
    a = dot(a, b)
    

    相当于

    dot(a, b)
    
    a = dot(a, b)
    
    例如,
    dot
    是numpy矩阵乘法函数,
    a
    b
    是矩阵

    你怎么能自己发现呢? 我也不知道该搜索什么,因为搜索Python文档或Google在包含@符号时不返回相关结果

    如果您想对特定的python语法有一个相当完整的了解,请直接查看语法文件。对于Python 3分支:

    ~$ grep -C 1 "@" cpython/Grammar/Grammar 
    
    decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
    decorators: decorator+
    --
    testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
    augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                '<<=' | '>>=' | '**=' | '//=')
    --
    arith_expr: term (('+'|'-') term)*
    term: factor (('*'|'@'|'/'|'%'|'//') factor)*
    factor: ('+'|'-'|'~') factor | power
    
    同样的概念也存在于类中,但在那里不太常用。 有关函数定义和类定义,请参见文档 更多关于装饰师的信息

    所以,我们看到了

    @foo
    def bar():
        pass
    
    在语义上与:

    def bar():
        pass
    
    bar = foo(bar)
    
    它们并不完全相同,因为Python使用decorator(
    @
    )语法在bar之前计算foo表达式(可以是点查找和函数调用),但在另一种情况下在bar之后计算foo表达式

    (如果这种差异对代码的意义产生了影响,你应该重新考虑你的生活,因为这是病态的。)

    堆叠装饰器 如果我们回到函数定义语法文档,我们会看到:

    大致相当于

    def func(): pass
    func = f1(arg)(f2(func))
    
    这是一个演示,我们可以调用一个函数,它首先是一个decorator,也可以调用堆栈decorator。在Python中,函数是第一类对象——这意味着您可以将函数作为参数传递给另一个函数,并返回函数。装饰师做这两件事

    如果我们堆叠decorators,那么函数(如定义的)将首先传递给它上面的decorator,然后传递给下一个,依此类推

    这是对装饰器上下文中
    @
    用法的总结

    操作员,
    @
    在语言参考的词法分析部分,我们有一个,其中包括
    @
    ,这使得它也是一个运算符:

    以下令牌是运算符:

    +       -       *       **      /       //      %      @
    <<      >>      &       |       ^       ~
    <       >       <=      >=      ==      !=
    
    [……] 调用这些方法来实现二进制算术运算(
    +
    -
    *
    @
    /
    ,[…]

    我们看到
    \uuuu matmul\uuuu
    对应于
    @
    。如果我们在文档中搜索“matmul”,我们会在标题“PEP 465-矩阵乘法专用中缀运算符”下找到“matmul”的链接

    它可以通过定义
    \uu matmul\umul()
    \umulta\umul()
    \uuuu imatmul\uuu()
    用于常规、反射和就地矩阵乘法

    class Mat(list):
        def __matmul__(self, B):
            A = self
            return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                        for j in range(len(B[0])) ] for i in range(len(A))])
    
    A = Mat([[1,3],[7,5]])
    B = Mat([[6,8],[4,2]])
    
    print(A @ B)
    
    (现在我们了解到,
    @=
    是就地版本)。它进一步解释:

    矩阵乘法是计算机许多领域中一种非常常见的运算 数学、科学、工程和@allows的添加 编写更干净的代码:

    S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)
    
    而不是:

    S = dot((dot(H, beta) - r).T,
            dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
    
    虽然此运算符可以重载以执行几乎任何操作,但例如,在
    numpy
    中,我们将使用此语法计算数组和矩阵的内积和外积:

    >>> from numpy import array, matrix
    >>> array([[1,2,3]]).T @ array([[1,2,3]])
    array([[1, 2, 3],
           [2, 4, 6],
           [3, 6, 9]])
    >>> array([[1,2,3]]) @ array([[1,2,3]]).T
    array([[14]])
    >>> matrix([1,2,3]).T @ matrix([1,2,3])
    matrix([[1, 2, 3],
            [2, 4, 6],
            [3, 6, 9]])
    >>> matrix([1,2,3]) @ matrix([1,2,3]).T
    matrix([[14]])
    
    就地矩阵乘法:
    @=
    在研究之前的用法时,
    >>> m = matrix([1,2,3])
    >>> m @= m.T
    >>> m
    matrix([[14]])
    
    df = pandas.DataFrame({'foo': [1,2,15,17]})
    y = 10
    df >> query('foo > @y') # plydata
    df.query('foo > @y') # pandas
    
    In [9]: def read_a_book():
       ...:     return "I am reading the book: "
       ...: 
    In [10]: read_a_book()
    Out[10]: 'I am reading the book: '
    
    def read_a_book():
        return "I am reading the book: 'Python Cookbook'"
    
    def add_a_book(func):
        def wrapper():
            return func() + "Python Cookbook"
        return wrapper
    
    In [14]: read_a_book = add_a_book(read_a_book)
    In [15]: read_a_book()
    Out[15]: 'I am reading the book: Python Cookbook'
    
    @add_a_book
    def read_a_book():
        return "I am reading the book: "
    In [17]: read_a_book()
    Out[17]: 'I am reading the book: Python Cookbook'
    
    import numpy as np
    def forward(xi, W1, b1, W2, b2):
        z1 = W1 @ xi + b1
        a1 = sigma(z1)
        z2 = W2 @ a1 + b2
        return z2, a1
    
    class WithoutDecorators:
    def some_static_method():
        print("this is static method")
    some_static_method = staticmethod(some_static_method)
    
    def some_class_method(cls):
        print("this is class method")
    some_class_method = classmethod(some_class_method)
    
    class WithDecorators:
        @staticmethod
        def some_static_method():
            print("this is static method")
    
        @classmethod
        def some_class_method(cls):
            print("this is class method")
    
    @some_decorator
    def decorated_function():
        pass
    
    def decorated_function():
        pass
    decorated_function = some_decorator(decorated_function)
    
    def mydecorator(function):
        def wrapped(*args, **kwargs):
            # do some stuff before the original
            # function gets called
            result = function(*args, **kwargs)
            # do some stuff after function call and
            # return the result
            return result
        # return wrapper as a decorated function
        return wrapped
    
    class DecoratorAsClass:
        def __init__(self, function):
            self.function = function
    
        def __call__(self, *args, **kwargs):
            # do some stuff before the original
            # function gets called
            result = self.function(*args, **kwargs)
            # do some stuff after function call and
            # return the result
            return result
    
    def repeat(number=3):
    """Cause decorated function to be repeated a number of times.
    
    Last value of original function call is returned as a result
    :param number: number of repetitions, 3 if not specified
    """
    def actual_decorator(function):
        def wrapper(*args, **kwargs):
            result = None
            for _ in range(number):
                result = function(*args, **kwargs)
            return result
        return wrapper
    return actual_decorator
    
    >>> @repeat(2)
    ... def foo():
    ...     print("foo")
    ...
    >>> foo()
    foo
    foo
    
    >>> @repeat()
    ... def bar():
    ...     print("bar")
    ...
    >>> bar()
    bar
    bar
    bar
    
    class Rectangle:
        def __init__(self, x1, y1, x2, y2):
            self.x1, self.y1 = x1, y1
            self.x2, self.y2 = x2, y2
    
        def _width_get(self):
            return self.x2 - self.x1
    
        def _width_set(self, value):
            self.x2 = self.x1 + value
    
        def _height_get(self):
            return self.y2 - self.y1
    
        def _height_set(self, value):
            self.y2 = self.y1 + value
    
        width = property(
            _width_get, _width_set,
            doc="rectangle width measured from left"
        )
        height = property(
            _height_get, _height_set,
            doc="rectangle height measured from top"
        )
    
        def __repr__(self):
            return "{}({}, {}, {}, {})".format(
                self.__class__.__name__,
                self.x1, self.y1, self.x2, self.y2
        )
    
    class Rectangle:
        def __init__(self, x1, y1, x2, y2):
            self.x1, self.y1 = x1, y1
            self.x2, self.y2 = x2, y2
    
        @property
        def width(self):
            """rectangle height measured from top"""
            return self.x2 - self.x1
    
        @width.setter
        def width(self, value):
            self.x2 = self.x1 + value
    
        @property
        def height(self):
            """rectangle height measured from top"""
            return self.y2 - self.y1
    
        @height.setter
        def height(self, value):
            self.y2 = self.y1 + value
    
    def function_decorator(func):
        def wrapped_func():
            # Do something before the function is executed
            func()
            # Do something after the function has been executed
        return wrapped_func
    
    @function_decorator
    def func():
        pass
    
    from functools import wraps
    
    def mydecorator(f):
        @wraps(f)
        def wrapped(*args, **kwargs):
            print "Before decorated function"
            r = f(*args, **kwargs)
            print "After decorated function"
            return r
        return wrapped
    
    @mydecorator
    def myfunc(myarg):
        print "my function", myarg
        return "return value"
    
    r = myfunc('asdf')
    print r
    
        Before decorated function
        my function asdf
        After decorated function
        return value