代码之家  ›  专栏  ›  技术社区  ›  ipramusinto

python中@是什么?[复制]

  •  0
  • ipramusinto  · 技术社区  · 7 年前

    我在看一些使用 @ 符号,但我不知道它是做什么的。我也不知道要搜索什么,因为搜索Python文档或Google没有返回相关结果时 @ 包括符号。

    0 回复  |  直到 8 年前
        1
  •  335
  •   user2357112    7 年前

    安 @ 行首的符号用于类、函数和方法 装饰工

    PEP 318: Decorators

    Python Decorators

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

    @property

    @classmethod

    @staticmethod

    如果你看到 @ 在一条直线的中间,这是另一回事,矩阵乘法。向下滚动查看其他答案 @

        2
  •  362
  •   Morgan Wilde    6 年前

    例子

    class Pizza(object):
        def __init__(self):
            self.toppings = []
    
        def __call__(self, topping):
            # When using '@instance_of_pizza' before a function definition
            # the function gets passed onto 'topping'.
            self.toppings.append(topping())
    
        def __repr__(self):
            return str(self.toppings)
    
    pizza = Pizza()
    
    @pizza
    def cheese():
        return 'cheese'
    @pizza
    def sauce():
        return 'sauce'
    
    print pizza
    # ['cheese', 'sauce']
    

    function / method / class 你在定义一个 基本上只是作为一个 argument 致 功能 / 方法 @ 签字。

    第一次看见

    瓶 介绍 从一开始,格式如下:

    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
    

    意识到这一点,我终于可以安心地和小酒瓶在一起了。

        3
  •  196
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    此代码段:

    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的定义中,可以添加一些函数通常不会返回的修改内容。

        4
  •  167
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    @ 作为一个操作员。它被命名为 __matmul__ PEP465 有关详细信息。

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

    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]]
    
        5
  •  115
  •   MattDMo    7 年前

    at(@)符号在Python中有什么作用?

    简言之,它用于装饰语法和矩阵乘法。

    在decorators上下文中,以下语法:

    @decorator
    def decorated_function():
        """this function is decorated"""
    

    相当于:

    def decorated_function():
        """this function is decorated"""
    
    decorated_function = decorator(decorated_function)
    

    a @ b 调用 a.__matmul__(b) -使用此语法:

    a @ b
    

    dot(a, b)
    

    和

    a @= b
    

    相当于

    a = dot(a, b)
    

    哪里 dot a 和 b 是矩阵。

    你怎么能自己发现这个?

    我也不知道要搜索什么,因为搜索Python文档或Google在包含@符号时不会返回相关结果。

    ~$ 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
    

    我们可以看到 @

    • 装饰工
    • 因子之间的运算符
    • 增广赋值算子

    修饰符语法:

    google搜索“decoratorpython docs”得到的最热门结果之一是“python语言参考”的“复合语句”部分 section on function definitions ,我们可以通过搜索单词“decorator”找到它,我们看到。。。有很多书要读。但话说回来, "decorator" is a link to the glossary ,它告诉我们:

    返回另一个函数的函数,通常用 @wrapper 语法。普通 装饰师的例子有 classmethod() 和 staticmethod()

    decorator语法仅仅是语法糖,下面两个 函数定义在语义上是等价的:

    def f(...):
        ...
    f = staticmethod(f)
    
    @staticmethod
    def f(...):
        ...
    

    同样的概念也存在于类中,但在那里不太常用。 有关函数定义和类定义,请参见文档

    所以,我们看到了

    @foo
    def bar():
        pass
    

    def bar():
        pass
    
    bar = foo(bar)
    

    它们并不完全相同,因为Python在bar之前用decorator计算foo表达式(可以是点式查找和函数调用)( @ )语法,但计算foo表达式 之后

    (如果这种差异使你的代码的意义发生了变化,你应该重新考虑你的生活,因为那将是病态的。)

    堆叠装饰工

    @f1(arg)
    @f2
    def func(): pass
    

    大致相当于

    def func(): pass
    func = f1(arg)(f2(func))
    

    这是一个演示,我们可以首先调用一个函数作为装饰器,以及堆栈装饰器。在Python中,函数是第一类对象,这意味着您可以将函数作为参数传递给另一个函数,然后返回函数。这两件事都是装修工做的。

    关于总结的用法 @ 在装饰师的背景下。

    接线员,

    在语言参考的词汇分析部分,我们有一个 section on operators ,包括 @ ,这使得它同时也是一个运算符:

    以下标记是运算符:

    +       -       *       **      /       //      %      @
    <<      >>      &       |       ^       ~
    <       >       <=      >=      ==      !=
    

    在下一页的数据模型中,我们有 Emulating Numeric Types ,

    object.__add__(self, other)
    object.__sub__(self, other) 
    object.__mul__(self, other) 
    object.__matmul__(self, other) 
    object.__truediv__(self, other) 
    object.__floordiv__(self, other)
    

    [...] 调用这些方法来实现二进制算术运算( + , - , * , , / // , [...]

    我们看到了 __matmul__ 对应于 @ . 如果我们在文档中搜索“matmul”,我们会得到一个链接 What's new in Python 3.5 在标题“PEP 465-矩阵乘法的专用中缀运算符”下加上“matmul”。

    它可以通过定义 __matmul__() , __rmatmul__() __imatmul__() 用于常规、反射和就地矩阵乘法。

    (所以现在我们知道了 @= 是就地版本)。它进一步解释了:

    矩阵乘法在许多领域是一种非常常见的运算 数学、科学、工程和@的添加允许 正在编写清理程序代码:

    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]])
    

    就地矩阵乘法: @=

    在研究以前的用法时,我们发现也存在矩阵的同位乘法。如果我们尝试使用它,我们可能会发现它还没有为numpy实现:

    >>> m = matrix([1,2,3])
    >>> m @= m.T
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.
    

    实施后,我希望结果如下:

    >>> m = matrix([1,2,3])
    >>> m @= m.T
    >>> m
    matrix([[14]])
    
        6
  •  41
  •   Wizard    8 年前

    at(@)符号在Python中有什么作用?

    @symbol是python提供的一种语法糖 decorator ,
    换句话来说,这正是关于decorator在Python中做什么的问题?

    简单点说 装饰工
    从第三方进口精美包装是最常见的情况。你可以想象它,你可以使用它,但你不能触及它的内心和内心。

    这里有个简单的例子,
    假设我定义一个 read_a_book

    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'
    

    @add_a_book read_a_book = add_a_book(read_a_book) ,这是一种语法上的甜点,没有什么比这更花哨的了。

        7
  •  17
  •   f__society    7 年前

    Numpy公司 那么,图书馆 @ operator 方法 矩阵乘法 . 例如:

    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
    
        8
  •  8
  •   dpodbori    10 年前

    从Python3.5开始,“@”被用作矩阵乘法的专用中缀符号(PEP 0465—请参阅 https://www.python.org/dev/peps/pep-0465/

        9
  •  8
  •   iun1x    7 年前

    在Python中添加了装饰器 功能与方法包装 (接收函数并返回增强的函数)更易于阅读和理解。最初的用例是能够将方法定义为类方法或定义头部的静态方法。如果没有decorator语法,它将需要一个相当稀疏和重复的定义:

    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)
    

    如果decorator语法用于相同的目的,则代码会更短,更易于理解:

    class WithDecorators:
        @staticmethod
        def some_static_method():
            print("this is static method")
    
        @classmethod
        def some_class_method(cls):
            print("this is class method")
    

    一般语法和可能的实现

    不允许使用lambda表达式 )它在调用时接受单个参数(它将是修饰函数),并返回另一个可调用对象。”这里用的是“可调用”而不是有预谋的“功能”。虽然decorator经常在方法和函数的范围内讨论,但它们并不局限于它们。事实上,任何可调用的对象(任何实现了call泳uMethod的对象都被认为是可调用的)都可以用作装饰器,并且它们返回的对象通常不是简单的函数,而是实现它们自己的call泳方法的更复杂类的更多实例。

    decorator语法只是 句法上的甜点 . 请考虑以下装饰器用法:

    @some_decorator
    def decorated_function():
        pass
    

    或始终可以被显式的或调用替换为:

    def decorated_function():
        pass
    decorated_function = some_decorator(decorated_function)
    

    但是,如果在一个函数上使用多个decorator,后者的可读性较差,也很难理解。 装饰器可以多种不同的方式使用,如下所示:

    有很多方法可以编写自定义修饰符,但最简单的方法是编写一个函数,该函数返回一个子函数来包装原始函数调用。

    一般模式如下:

    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
    

    作为一个班级

    虽然decorator几乎总是可以使用函数实现的,但是在某些情况下,使用用户定义的类是一个更好的选择。当decorator需要复杂的参数化或它依赖于特定的状态时,这通常是正确的。

    非参数化装饰器作为类的泛型模式如下:

    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
    

    这样定义的decorator可以接受参数:

    >>> @repeat(2)
    ... def foo():
    ...     print("foo")
    ...
    >>> foo()
    foo
    foo
    

    请注意,即使参数化装饰器的参数有默认值,它的名称后面的括号也是必需的。将前面的decorator与默认参数一起使用的正确方法如下:

    >>> @repeat()
    ... def bar():
    ...     print("bar")
    ...
    >>> bar()
    bar
    bar
    bar
    

    最后让我们看看具有属性的装饰器。

    属性

    属性提供了一个内置的 descriptor 知道如何将属性链接到一组方法的类型。属性接受四个可选参数:fget、fset、fdel和doc。最后一个可以用来定义一个docstring,它链接到属性,就好像它是一个方法一样。下面是一个矩形类的示例,该类可以通过直接访问存储两个角点的属性或使用宽度和高度属性进行控制:

    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
        )
    

    创建属性的最佳语法是将property用作装饰器。这个遗嘱 减少方法签名的数量 课堂内部 让代码更丰富 可读性和可维护性 . 对于decorators,上面的类变成:

    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
    
        10
  •  2
  •   Peter Rowell    15 年前

    它表示您正在使用装饰器。给你 Bruce Eckel's example 从2008年开始。

        11
  •  2
  •   Mayur Patel    12 年前

    在Python中,它就像:

    1. 创建函数(在@call下面)
    2. 用返回的新函数替换定义的函数。

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

        12
  •  2
  •   Aswin    8 年前

    @symbol还用于访问plydata/pandas数据帧查询中的变量, pandas.DataFrame.query 例子:

    df = pandas.DataFrame({'foo': [1,2,15,17]})
    y = 10
    df >> query('foo > @y') # plydata
    df.query('foo > @y') # pandas