Ik kijk naar een Python-code die het symbool @
gebruikte, maar ik heb geen idee wat het doet. Ik weet ook niet waar ik naar moet zoeken, omdat zoeken in Python-documenten of Google geen relevante resultaten oplevert als het @
-symbool is opgenomen.
Antwoord 1, autoriteit 100%
Een @
symbool aan het begin van een regel wordt gebruikt voor klasse, functie en methode decorators.
Lees hier meer:
De meest voorkomende Python-decorateurs die je tegenkomt zijn:
Als je een @
in het midden van een regel ziet, is dat iets anders, matrixvermenigvuldiging. Zie dit antwoord waarin het gebruik van @
als binaire operator wordt getoond.
Antwoord 2, autoriteit 98%
Voorbeeld
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']
Dit toont aan dat de function
/method
/class
die u definieert nadat een decorateurin feite doorgegeven als een argument
aan de function
/method
direct na het @
-teken.
Eerste waarneming
De microframework Flaskintroduceert decorateursvanaf het allereerste begin in het volgende formaat:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
Dit vertaalt zich op zijn beurt in:
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
Toen ik me dit realiseerde, voelde ik me eindelijk in vrede met Flask.
Antwoord 3, autoriteit 56%
Dit codefragment:
def decorator(func):
return func
@decorator
def some_func():
pass
Is gelijk aan deze code:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
In de definitie van een decorateur kun je enkele gewijzigde dingen toevoegen die normaal niet door een functie worden geretourneerd.
Antwoord 4, autoriteit 49%
In Python 3.5 kun je als operator @
overbelasten. Het heet __matmul__
, omdat het is ontworpen om matrixvermenigvuldiging uit te voeren, maar het kan alles zijn wat je maar wilt. Zie PEP465voor details.
Dit is een eenvoudige implementatie van matrixvermenigvuldiging.
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)
Deze code levert op:
[[18, 14], [62, 66]]
Antwoord 5, autoriteit 15%
Wat doet het at (@)-symbool in Python?
@-symbool is een syntactische suikerpython om decorator
te gebruiken,
om de vraag te parafraseren: het gaat er precies om wat decorateur doet in Python?
Eenvoudig gezegd decorator
stelt u in staat de definitie van een bepaalde functie te wijzigen zonder de binnenste (het is sluiting) aan te raken.
Het is het meest het geval wanneer u een prachtig pakket van een derde partij importeert. Je kunt het visualiseren, je kunt het gebruiken, maar je kunt het binnenste en het hart ervan niet aanraken.
Hier is een snel voorbeeld,
stel dat ik een read_a_book
functie definieer op Ipython
In [9]: def read_a_book():
...: return "I am reading the book: "
...:
In [10]: read_a_book()
Out[10]: 'I am reading the book: '
Zie je, ik ben vergeten er een naam aan toe te voegen.
Hoe een dergelijk probleem op te lossen? Natuurlijk zou ik de functie opnieuw kunnen definiëren als:
def read_a_book():
return "I am reading the book: 'Python Cookbook'"
Desalniettemin, wat als ik de oorspronkelijke functie niet mag manipuleren, of als er duizenden van dergelijke functies moeten worden afgehandeld.
Los het probleem op door anders te denken en definieer een nieuwe_functie
def add_a_book(func):
def wrapper():
return func() + "Python Cookbook"
return wrapper
Gebruik het dan.
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'
Tada, zie je, ik heb read_a_book
aangepast zonder de binnenste sluiting aan te raken. Niets houdt me tegen om uitgerust te zijn met decorator
.
Hoe zit het met @
@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
is een mooie en handige manier om read_a_book = add_a_book(read_a_book)
te zeggen, het is een syntactische suiker, er is niets mooiers aan.
Antwoord 6, autoriteit 5%
Als je verwijst naar een code in een python-notebook die de Numpy-bibliotheek gebruikt, dan betekent @ operator
Matrix-vermenigvuldiging. Bijvoorbeeld:
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
Antwoord 7, autoriteit 3%
Decorators zijn toegevoegd in Python om function en method wrapping(een functie die een functie ontvangt en een verbeterde retourneert) gemakkelijker leesbaar en begrijpelijk te maken. De oorspronkelijke use case was om de methoden te kunnen definiëren als klassenmethoden of statische methoden op de kop van hun definitie. Zonder de syntaxis van de decorateur zou een nogal schaarse en repetitieve definitie nodig zijn:
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)
Als de syntaxis van de decorateur voor hetzelfde doel wordt gebruikt, is de code korter en gemakkelijker te begrijpen:
class WithDecorators:
@staticmethod
def some_static_method():
print("this is static method")
@classmethod
def some_class_method(cls):
print("this is class method")
Algemene syntaxis en mogelijke implementaties
De decorateur is over het algemeen een benoemd object ( lambda-expressies zijn niet toegestaan) dat een enkel argument accepteert wanneer het wordt aangeroepen (het zal de gedecoreerde functie zijn) en een andere oproepbare retourneert object. “Oproepbaar” wordt hier gebruikt in plaats van “functie” met voorbedachte rade. Hoewel decorateurs vaak worden besproken in het kader van methoden en functies, zijn ze daar niet toe beperkt. In feite kan alles dat kan worden aangeroepen (elk object dat de _call__-methode implementeert, als aanroepbaar worden beschouwd), kan worden gebruikt als een decorateur en vaak zijn objecten die door hen worden geretourneerd geen eenvoudige functies, maar meer instanties van complexere klassen die hun eigen __call_-methode implementeren.
De syntaxis van de decorateur is gewoon een syntactische suiker. Overweeg het volgende gebruik van decorateurs:
@some_decorator
def decorated_function():
pass
Dit kan altijd worden vervangen door een expliciete aanroep van de decorateur en functiehertoewijzing:
def decorated_function():
pass
decorated_function = some_decorator(decorated_function)
Dit laatste is echter minder leesbaar en ook erg moeilijk te begrijpen als meerdere decorateurs op één functie worden gebruikt.
Decorateurs kunnen op verschillende manieren worden gebruikt, zoals hieronder weergegeven:
Als functie
Er zijn veel manieren om aangepaste decorateurs te schrijven, maar de eenvoudigste manier is om een functie te schrijven die een subfunctie retourneert die de oorspronkelijke functieaanroep omhult.
De algemene patronen zijn als volgt:
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
Als klas
Hoewel decorateurs bijna altijd kunnen worden geïmplementeerd met behulp van functies, zijn er situaties waarin het gebruik van door de gebruiker gedefinieerde klassen een betere optie is. Dit is vaak het geval wanneer de decorateur complexe parametrisering nodig heeft of het afhankelijk is van een specifieke staat.
Het algemene patroon voor een niet-geparametriseerde decorateur als klasse is als volgt:
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
Decorateurs parametriseren
In echte code is het vaak nodig om decorateurs te gebruiken die kunnen worden geparametreerd. Wanneer de functie als decorateur wordt gebruikt, is de oplossing eenvoudig: er moet een tweede verpakkingsniveau worden gebruikt. Hier is een eenvoudig voorbeeld van de decorateur die de uitvoering van een versierde functie het gespecificeerde aantal keren herhaalt elke keer dat deze wordt aangeroepen:
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
De decorateur die op deze manier is gedefinieerd, kan parameters accepteren:
>>> @repeat(2)
... def foo():
... print("foo")
...
>>> foo()
foo
foo
Merk op dat zelfs als de geparametriseerde decorateur standaardwaarden heeft voor zijn argumenten, de haakjes achter de naam vereist zijn. De juiste manier om de voorgaande decorateur met standaardargumenten te gebruiken is als volgt:
>>> @repeat()
... def bar():
... print("bar")
...
>>> bar()
bar
bar
bar
Laat eindelijk decorateurs zien met Eigenschappen.
Eigenschappen
De eigenschappen bieden een ingebouwd descriptor-type dat weet een attribuut te koppelen aan een set methoden. Een eigenschap heeft vier optionele argumenten: fget , fset , fdel en doc . De laatste kan worden opgegeven om een docstring te definiëren die aan het attribuut is gekoppeld alsof het een methode is. Hier is een voorbeeld van een klasse Rectangle die kan worden beheerd door directe toegang tot attributen die twee hoekpunten opslaan of door de eigenschappen width en height te gebruiken:
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
)
De beste syntaxis voor het maken van eigenschappen is het gebruik van eigenschap als decorateur. Dit zal het aantal methodehandtekeningen verminderenbinnen de klasse
en code leesbaarder en beter te onderhoudente maken. Bij decorateurs wordt de bovenstaande klasse:
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
Antwoord 8, autoriteit 3%
Vanaf Python 3.5 wordt de ‘@’ gebruikt als een speciaal tussenvoegselsymbool voor MATRIX MULTIPLICATIE (PEP 0465 — zie https://www.python.org/dev/peps/pep-0465/)
Antwoord 9
Het geeft aan dat je een decorateur gebruikt. Hier is Bruce Eckels voorbeelduit 2008.
Antwoord 10
Om op een andere manier te zeggen wat anderen hebben: ja, het is een decorateur.
In Python is het zoiets als:
- Een functie maken (volgt onder de @-aanroep)
- Een andere functie aanroepen om uw gemaakte functie te bedienen. Dit levert een nieuwe functie op. De functie die je aanroept is het argument van de @.
- De gedefinieerde functie vervangen door de nieuwe functie die is geretourneerd.
Dit kan voor allerlei nuttige dingen worden gebruikt, mogelijk gemaakt omdat functies objecten zijn en alleen noodzakelijke instructies.
Antwoord 11
@-symbool wordt ook gebruikt om toegang te krijgen tot variabelen in een plydata / pandas dataframe-query, pandas.DataFrame.query
.
Voorbeeld:
df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas
Antwoord 12
Python-decorateur is als een wrapper van een functie of een klasse. Het is nog te conceptueel.
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
De bovenstaande code is een definitie van een decorateur die een functie decoreert.
function_decorator is de naam van de decorateur.
wrapped_funcis de naam van de innerlijke functie, die eigenlijk alleen in deze decorateurdefinitie wordt gebruikt. funcis de functie die wordt ingericht.
In de innerlijke functie wrapped_funckunnen we alles doen voor en nadat de funcwordt aangeroepen. Nadat de decorateur is gedefinieerd, gebruiken we deze eenvoudig als volgt.
@function_decorator
def func():
pass
Als we vervolgens de functie funcaanroepen, worden de gedragingen die we hebben gedefinieerd in de decorateur ook uitgevoerd.
VOORBEELD:
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
Uitvoer:
Before decorated function
my function asdf
After decorated function
return value
Antwoord 13
@ kan een wiskundige operator of DECORATOR zijn, maar je bedoelt een decorateur
zie volgende code
def func(f):
return f
func(lambda :"HelloWorld")()
als het gebruik van decorateurs het kan schrijven
def func(f):
return f
@func
def name():
return "Hello World"
name()
decorateurs kunnen ruzie hebben
De GeeksforGeeks schrijven dit bericht https://www.geeksforgeeks.org/decorators-in -python/