Wat doet het at (@)-symbool in Python?

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:

PEP 318: Decorateurs

Python-decorateurs

De meest voorkomende Python-decorateurs die je tegenkomt zijn:

@property

@classmethod

@staticmethod

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/classdie u definieert nadat een decorateurin feite doorgegeven als een argumentaan de function/methoddirect 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 decoratorte gebruiken,
om de vraag te parafraseren: het gaat er precies om wat decorateur doet in Python?

Eenvoudig gezegd decoratorstelt 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_bookfunctie 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_bookaangepast 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_bookis 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 @ operatorMatrix-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:

  1. Een functie maken (volgt onder de @-aanroep)
  2. 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 @.
  3. 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/

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes