답변:
@
줄의 시작 부분에 있는 기호는 클래스, 함수 및 메소드 데코레이터에 사용 됩니다.
더 많은 것을 읽으십시오 :
가장 일반적인 파이썬 데코레이터는 다음과 같습니다.
당신이 표시되는 경우 @
라인의 중간에, 그것은 다른 것, 행렬 곱셈이다. 아래로 스크롤하여를 사용하는 다른 답변을 봅니다 @
.
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
이것을 깨닫고 마침내 플라스크와 평화를 느낄 수있었습니다.
app.route("/")
이 함수는 함수를 반환으로 호출하는 당신을 당신의 : hello()
인수로
app.route("/", hello)
정의 직후에 호출하는 것 hello
또는 심지어 hello
인수에 대한 람다로 정의하는 대신에 데코레이터를 사용하면 구문 또는 실제 이점은 무엇 app.route
입니까? (후자의 예는 Node.js http.Server
및 Express 경로와 공통입니다 .)
이 코드 스 니펫 :
def decorator(func):
return func
@decorator
def some_func():
pass
이 코드와 동일합니다 :
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
데코레이터 정의에서 정상적으로 함수에 의해 반환되지 않는 수정 된 것을 추가 할 수 있습니다.
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]]
@=
(인플레 이스) 연산자 인입니다 __imatmul__
.
__add__
있고 __sub__
연결되어 있지만 @
이전에 사인을 들어 본 적이 없습니다 . 거기에 숨어있는 다른 사람들이 있습니까?
간단히 말해서 데코레이터 구문과 행렬 곱셈에 사용됩니다.
데코레이터와 관련하여이 구문은 다음과 같습니다.
@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와 기능하고 a
및 b
행렬이다.
@ 기호가 포함되어 있으면 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]])
“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)
. 그것은 구문 설탕이며 그것에 대해 더 멋진 것은 없습니다.
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
데코레이터는 함수와 메소드 래핑 (함수를 수신하고 개선 된 함수를 리턴하는 함수)을 더 쉽게 읽고 이해 하도록 파이썬에 추가되었습니다 . 원래 유스 케이스는 메소드를 정의의 선두에 클래스 메소드 또는 정적 메소드로 정의 할 수있었습니다. 데코레이터 구문이 없으면 다소 희박하고 반복적 인 정의가 필요합니다.
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
데코레이터를 사용하고 있음을 나타냅니다. 다음은 2008 년 의 Bruce Eckel의 예 입니다.