“at”(@) 기호는 파이썬에서 무엇을합니까?


579

@기호 를 사용한 일부 Python 코드를보고 있지만 그 기능이 무엇인지 전혀 모릅니다. 또한 파이썬 문서를 검색하거나 @기호가 포함될 때 Google이 관련 결과를 반환하지 않으므로 검색 대상을 알지 못합니다 .

답변:


303

@줄의 시작 부분에 있는 기호는 클래스, 함수 및 메소드 데코레이터에 사용 됩니다.

더 많은 것을 읽으십시오 :

PEP 318 : 데코레이터

파이썬 데코레이터

가장 일반적인 파이썬 데코레이터는 다음과 같습니다.

@특성

@classmethod

static

당신이 표시되는 경우 @라인의 중간에, 그것은 다른 것, 행렬 곱셈이다. 아래로 스크롤하여를 사용하는 다른 답변을 봅니다 @.


31
또한 행렬 곱셈 연산자가 될 수도 있습니다. stackoverflow.com/a/21563036/5049813
Pro Q

@decorators도 추가 할 수 있습니다
비제이 Panchal에게

347

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받는 사람 function/ method즉시 후 @로그인합니다.

첫 목격

마이크로 프레임 워크 플라스크 는 처음부터 다음 형식으로 데코레이터 를 소개 합니다.

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

이것을 깨닫고 마침내 플라스크와 평화를 느낄 수있었습니다.


7
케이스 술병의에서 app.route("/")이 함수는 함수를 반환으로 호출하는 당신을 당신의 : hello()인수로
shaqed

3
예를 들어 , app.route("/", hello)정의 직후에 호출하는 것 hello또는 심지어 hello인수에 대한 람다로 정의하는 대신에 데코레이터를 사용하면 구문 또는 실제 이점은 무엇 app.route입니까? (후자의 예는 Node.js http.Server및 Express 경로와 공통입니다 .)
iono

185

이 코드 스 니펫 :

def decorator(func):
   return func

@decorator
def some_func():
    pass

이 코드와 동일합니다 :

def decorator(func):
    return func

def some_func():
    pass

some_func = decorator(some_func)

데코레이터 정의에서 정상적으로 함수에 의해 반환되지 않는 수정 된 것을 추가 할 수 있습니다.


1
이 줄 s "ome_func = decorator (some_func)"에서 첫 번째 some_func는 변수 = 함수 some_func에 대한 것입니까?
Viragos

147

Python 3.5에서는 @연산자로 오버로드 할 수 있습니다 . 그것은으로 이름 __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]]

14
또한 @=(인플레 이스) 연산자 인입니다 __imatmul__.
Pål GD

이와 같은 재정의 가능한 다른 연산자가 있습니까? 나는 +와-를 각각 알고 __add__있고 __sub__연결되어 있지만 @이전에 사인을 들어 본 적이 없습니다 . 거기에 숨어있는 다른 사람들이 있습니까?
Thomas Kimber

103

“at”(@) 기호는 파이썬에서 무엇을합니까?

간단히 말해서 데코레이터 구문과 행렬 곱셈에 사용됩니다.

데코레이터와 관련하여이 구문은 다음과 같습니다.

@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, 예를 들어, 행렬 곱셈 NumPy와 기능하고 ab행렬이다.

어떻게 스스로 이것을 발견 할 수 있습니까?

@ 기호가 포함되어 있으면 Python 문서를 검색하거나 Google이 관련 결과를 반환하지 않으므로 검색 대상을 알지 못합니다.

특정 파이썬 구문이 무엇을하는지 완전히 이해하려면 문법 파일을 직접보십시오. 파이썬 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

우리는 여기 @에서 세 가지 상황에서 사용되는 것을 볼 수 있습니다.

  • 데코레이터
  • 요인들 사이의 연산자
  • 증강 할당 연산자

데코레이터 구문 :

"decorator python docs"에 대한 Google 검색은 "Python Language Reference"의 "Compound Statements"섹션의 최상위 결과 중 하나입니다. "decorator"라는 단어를 검색하여 찾을 수있는 함수 정의 섹션으로 스크롤 하면 읽을 내용이 많이 있습니다. 그러나 "장식 자" 라는 단어 는 용어집연결되어 있습니다 .

데코레이터

일반적으로 @wrapper구문을 사용하여 함수 변환으로 적용되는 다른 함수를 반환하는 함수 입니다. 데코레이터의 일반적인 예는 classmethod()staticmethod()입니다.

데코레이터 구문은 단순한 구문 설탕이며 다음 두 함수 정의는 의미 상 동일합니다.

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

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

동일한 개념이 클래스에 존재하지만 덜 일반적으로 사용됩니다. 데코레이터에 대한 자세한 내용은 함수 정의 및 클래스 정의에 대한 설명서를 참조하십시오.

그래서 우리는

@foo
def bar():
    pass

의미 적으로 다음과 같습니다.

def bar():
    pass

bar = foo(bar)

파이썬은 데코레이터 ( @) 구문을 사용하여 bar 이전에 foo 표현식 (점선 조회 및 함수 호출 일 수 있음)을 평가하지만 다른 경우 bar 의 foo 표현식 평가하기 때문에 정확히 동일하지는 않습니다 .

(이러한 차이점이 코드의 의미에 차이가있는 경우 병리학적인 것이기 때문에 인생에서하고있는 일을 재고해야합니다.)

누적 데코레이터

함수 정의 구문 문서로 돌아 가면 다음을 볼 수 있습니다.

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

대략적으로

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

이것은 데코레이터 인 함수와 스택 데코레이터를 먼저 호출 할 수 있다는 것을 보여줍니다. 파이썬에서 함수는 일급 객체입니다. 즉, 함수를 다른 함수의 인수로 전달하고 함수를 반환 할 수 있습니다. 데코레이터는이 두 가지를 모두 수행합니다.

데코레이터를 쌓으면 정의 된대로 함수가 먼저 데코레이터에게 전달되고 그 다음에 계속 전달됩니다.

그것은 @데코레이터의 맥락에서 사용법을 요약합니다 .

운영자, @

언어 참조의 어휘 분석 섹션 에는 연산자에 대한 섹션 이 있으며 여기에는 연산자 가 포함됩니다 @.

다음 토큰은 연산자입니다.

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

다음 페이지에서, 데이터 모델, 우리는 절로 Emulation 소프트웨어 숫자 유형 ,

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"에 대한 문서를 검색하면 "PEP 465-행렬 곱셈을위한 전용 접두사 연산자"아래에 "matmul"이 있는 Python 3.5의 새로운 기능에 대한 링크가 표시됩니다 .

이것은 정의에 의해 구현 될 수있다 __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]])

36

“at”(@) 기호는 파이썬에서 무엇을합니까?

@ 기호는 구문 설탕 파이썬 활용 제공하는 것입니다 decorator,
그것은 정확히 파이썬으로 장식 않는 무엇에 대해 질문을 의역하는거야?

간단히 말하면 decorator주어진 함수의 정의를 가장 안쪽에 닿지 않고 수정할 수 있습니다 (닫힘).
타사에서 멋진 패키지를 가져 오는 경우가 가장 많습니다. 당신은 그것을 시각화하고 사용할 수는 있지만 가장 안쪽과 마음을 만질 수는 없습니다.

다음은 간단한 예 입니다 .Ipython
에서 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'"

그럼에도 불구하고 원래 기능을 조작 할 수 없거나 처리 할 수천 가지 기능이있는 경우 어떻게해야합니까?

다르게 생각하여 문제를 해결하고 new_function을 정의하십시오.

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'

타다, 당신은 read_a_book내부 폐쇄를 건드리지 않고 수정 했습니다. 아무것도 나를 장착 중지합니다 decorator.

무엇에 관한 것 @

@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). 그것은 구문 설탕이며 그것에 대해 더 멋진 것은 없습니다.


16

Numpy 라이브러리를 사용하는 파이썬 노트북에서 일부 코드를 참조하는 경우 Matrix Multiplication@ 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

Python 3.5부터 '@'은 MATRIX MULTIPLICATION (PEP 0465- https: //www.python.org/dev/peps/pep-0465/ 참조 ) 의 전용 접두사 기호로 사용됩니다.


6

데코레이터는 함수와 메소드 래핑 (함수를 수신하고 개선 된 함수를 리턴하는 함수)을 더 쉽게 읽고 이해 하도록 파이썬에 추가되었습니다 . 원래 유스 케이스는 메소드를 정의의 선두에 클래스 메소드 또는 정적 메소드로 정의 할 수있었습니다. 데코레이터 구문이 없으면 다소 희박하고 반복적 인 정의가 필요합니다.

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

일반적인 구문과 가능한 구현

데코레이터는 일반적으로 이름이 지정된 객체 ( 람다 식은 허용되지 않음 )이며 호출시 단일 인수를 허용하고 (장식 된 함수가 됨) 다른 호출 가능한 객체를 반환합니다. 여기서는 "함수"대신 "통화 가능"이 사용됩니다. 데코레이터는 종종 방법과 기능의 범위에서 논의되지만, 이것들에 국한되지는 않습니다. 실제로, 호출 가능한 모든 것 (_call__ 메소드를 구현하는 모든 객체는 호출 가능한 것으로 간주 됨)은 데코레이터로 사용될 수 있으며 종종 그들에 의해 리턴 된 객체는 단순한 함수가 아니라 더 많은 고유 클래스 __call_ 메소드를 구현하는 더 많은 인스턴스입니다.

데코레이터 구문은 단순히 구문 설탕 일뿐 입니다. 다음 데코레이터 사용법을 고려하십시오.

@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

마지막으로 속성이있는 데코레이터를 볼 수 있습니다.

속성

특성 은 속성을 메소드 세트에 링크하는 방법을 알고 있는 내장 디스크립터 유형을 제공 합니다. 속성에는 fget, fset, fdel 및 doc의 네 가지 선택적 인수가 사용됩니다. 마지막 메소드는 속성 인 것처럼 메소드에 링크 된 docstring을 정의하기 위해 제공 될 수 있습니다. 다음은 두 개의 모퉁이 점을 저장하는 속성에 직접 액세스하거나 width 및 height 속성을 사용하여 제어 할 수있는 Rectangle 클래스의 예입니다.

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

2

다른 사람들이 다른 방식으로 무엇을 말하는지 : 예, 그것은 데코레이터입니다.

파이썬에서는 다음과 같습니다.

  1. 함수 작성 (@ 호출에서 수행)
  2. 작성된 함수에서 작동하기 위해 다른 함수를 호출합니다. 새로운 함수를 반환합니다. 호출하는 함수는 @의 인수입니다.
  3. 반환 된 새 함수로 정의 된 함수를 교체합니다.

이것은 모든 종류의 유용한 것들에 사용될 수 있습니다. 함수는 객체이고 단지 명령 만 필요하기 때문에 가능했습니다.


2

@ 기호는 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.