statische methoden in Python?

Is het mogelijk om statische methoden in Python te hebben die ik zou kunnen bellen zonder een klasse te initialiseren, zoals:

ClassName.static_method()

Antwoord 1, Autoriteit 100%

YEP, gebruikmakend van de staticmethod decorator

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print(x)
MyClass.the_static_method(2)  # outputs 2

Merk op dat een code kan gebruiken de oude methode om een ​​statische methode te definiëren, met behulp van staticmethodals een functie in plaats van een decorator. Dit mag alleen worden gebruikt als u oude versies van Python (2.2 en 2.3)

moet ondersteunen

class MyClass(object):
    def the_static_method(x):
        print(x)
    the_static_method = staticmethod(the_static_method)
MyClass.the_static_method(2)  # outputs 2

Dit is volledig identiek aan het eerste voorbeeld (met behulp van @staticmethod), alleen niet gebruiken van de Nice Decorator-syntaxis

Ten slotte, gebruik staticmethodspaarzaam! Er zijn maar weinig situaties waarin statische-methoden nodig zijn in Python, en ik heb ze vele malen gezien waar een afzonderlijke “top-level” -functie duidelijker zou zijn geweest.


Het volgende is woordelijk is van de documentatie: :

Een statische methode ontvangt geen impliciet eerste argument. Gebruik dit idioom om een ​​statische methode te declareren:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ...

Het @Staticmethod-formulier is een functie Decorator – Zie de beschrijving van functiedefinities in Functie-definities voor details.

het kan worden genoemd op de klas (zoals C.f()) of op een instantie (zoals C().f()). Het exemplaar wordt genegeerd, behalve voor zijn klasse.

Statische methoden in Python zijn vergelijkbaar met die gevonden in Java of C++. Zie classmethod().

Raadpleeg voor meer informatie over statische methoden de documentatie op de standaardtype Hiërarchie in De standaardtypehiërarchie .

Nieuw in versie 2.2.

Gewijzigd in versie 2.4: FUNCTION DECORATOR SYNTAX TOEGEVOEGD.


Antwoord 2, Autoriteit 11%

Ik denk dat STEVEN eigenlijk goed . Om de oorspronkelijke vraag te beantwoorden, gaat u vervolgens aan om een ​​klassenmethode in te stellen, eenvoudigweg dat het eerste argument geen oproepinstantie is en zorg ervoor dat u alleen de methode van de klasse belt.

(Merk op dat dit antwoord verwijst naar Python 3.x. In Python 2.x krijg je een TypeErrorvoor het aanroepen van de methode op de klasse zelf.)

Bijvoorbeeld:

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable
    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)
    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))
    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

In deze code gaat de “rollCall”-methode ervan uit dat het eerste argument geen instantie is (zoals het zou zijn als het zou worden aangeroepen door een instantie in plaats van door een klasse). Zolang “rollCall” wordt aangeroepen vanuit de klasse in plaats van een instantie, werkt de code prima. Als we proberen “rollCall” te bellen vanaf een instantie, bijvoorbeeld:

rex.rollCall(-1)

het zou echter een uitzondering veroorzaken omdat het twee argumenten zou verzenden: zichzelf en -1, en “rollCall” is alleen gedefinieerd om één argument te accepteren.

Overigens, rex.rollCall() zou het juiste aantal argumenten verzenden, maar zou ook een uitzondering veroorzaken omdat n nu een Dog-instantie (dwz rex) zou vertegenwoordigen wanneer de functie verwacht dat n numeriek is.

Dit is waar de decoratie van pas komt:
Als we de “rollCall”-methode voorafgaan met

@staticmethod

door expliciet te vermelden dat de methode statisch is, kunnen we deze zelfs vanuit een instantie aanroepen. Nu,

rex.rollCall(-1)

zou werken. Het invoegen van @staticmethod voor een methodedefinitie zorgt er dan voor dat een instantie zichzelf niet als argument verzendt.

Je kunt dit verifiëren door de volgende code te proberen, met en zonder commentaar op de @staticmethod-regel.

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable
    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)
    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))
    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)

Antwoord 3, autoriteit 4%

Ja, bekijk de staticmethod-decorateur:

>>> class C:
...     @staticmethod
...     def hello():
...             print "Hello World"
...
>>> C.hello()
Hello World

Antwoord 4, autoriteit 3%

Je hoeft de decorator @staticmethodniet echt te gebruiken. Gewoon een methode declareren (die de self-parameter niet verwacht) en deze vanuit de klasse aanroepen. De decorateur is er alleen als je hem ook vanuit een instantie wilt kunnen aanroepen (wat niet was wat je wilde doen)

Meestal gebruik je echter gewoon functies…


Antwoord 5, autoriteit 2%

Statische methoden in Python?

Is het mogelijk om statische methoden in Python te hebben, zodat ik ze kan aanroepen?
zonder een klasse te initialiseren, zoals:

ClassName.StaticMethod()

Ja, statische methoden kunnen op deze manier worden gemaakt (hoewel het een beetje meer is Pythonicom underscores te gebruiken in plaats van CamelCase voor methoden):

class ClassName(object):
    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

Het bovenstaande gebruikt de syntaxis van de decorateur. Deze syntaxis is gelijk aan

class ClassName(object):
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''
    static_method = staticmethod(static_method)

Dit kan worden gebruikt zoals je hebt beschreven:

ClassName.static_method()

Een ingebouwd voorbeeld van een statische methode is str.maketrans()in Python 3, wat een functie was in de string-module in Python 2.


Een andere optie die kan worden gebruikt als u beschrijft, is de classmethod, het verschil is dat de ClassMethod de klasse krijgt als een impliciet eerste argument, en indien geslaagd, dan krijgt het de subklasse als het impliciete eerste argument.

class ClassName(object):
    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

Merk op dat clsgeen vereiste naam is voor het eerste argument, maar de meest ervaren Python-coders zullen het slecht doen als u iets anders gebruikt.

Deze worden meestal gebruikt als alternatieve constructeurs.

new_instance = ClassName.class_method()

Een tweedehands voorbeeld is dict.fromkeys():

new_dict = dict.fromkeys(['key1', 'key2'])

Antwoord 6

Afgezien van de bijzonderheden van hoe statische methode objecten gedragen zich daar Is een bepaald soort schoonheid die je kunt slaan als het gaat om het organiseren van je module-niveau-code.

# garden.py
def trim(a):
    pass
def strip(a):
    pass
def bunch(a, b):
    pass
def _foo(foo):
    pass
class powertools(object):
    """
    Provides much regarded gardening power tools.
    """
    @staticmethod
    def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
        return 42
    @staticmethod
    def random():
        return 13
    @staticmethod
    def promise():
        return True
def _bar(baz, quux):
    pass
class _Dice(object):
    pass
class _6d(_Dice):
    pass
class _12d(_Dice):
    pass
class _Smarter:
    pass
class _MagicalPonies:
    pass
class _Samurai:
    pass
class Foo(_6d, _Samurai):
    pass
class Bar(_12d, _Smarter, _MagicalPonies):
    pass

# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
    pass
class PowertoolsTests(unittest.TestCase):
    pass
class FooTests(unittest.TestCase):
    pass
class BarTests(unittest.TestCase):
    pass

# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())

# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
    def hit():
        return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
    pass

Het wordt nu een beetje intuïtiever en zelfdocumenterend in welke context bepaalde componenten bedoeld zijn om te worden gebruikt en het is ideaal voor het benoemen van verschillende testgevallen en voor een eenvoudige benadering van hoe testmodules worden toegewezen aan daadwerkelijke modules onder tests voor puristen.

Ik vind het vaak haalbaar om deze benadering toe te passen bij het organiseren van de hulpprogrammacode van een project. Heel vaak haasten mensen zich onmiddellijk en maken een utils-pakket en eindigen met 9 modules waarvan één 120 LOC heeft en de rest op zijn best twee dozijn LOC is. Ik geef er de voorkeur aan om hiermee te beginnen en het om te zetten in een pakket en alleen modules te maken voor de beesten die ze echt verdienen:

# utils.py
class socket(object):
    @staticmethod
    def check_if_port_available(port):
        pass
    @staticmethod
    def get_free_port(port)
        pass
class image(object):
    @staticmethod
    def to_rgb(image):
        pass
    @staticmethod
    def to_cmyk(image):
        pass

Antwoord 7

Misschien is de eenvoudigste optie om die functies buiten de klas te plaatsen:

class Dog(object):
    def __init__(self, name):
        self.name = name
    def bark(self):
        if self.name == "Doggy":
            return barking_sound()
        else:
            return "yip yip"
def barking_sound():
    return "woof woof"

Met deze methode kunnen functies die de interne objectstatus wijzigen of gebruiken (met bijwerkingen) in de klasse worden gehouden en kunnen de herbruikbare hulpprogrammafuncties naar buiten worden verplaatst.

Stel dat dit bestand dogs.pyheet. Om deze te gebruiken, roep je dogs.barking_sound()aan in plaats van dogs.Dog.barking_sound.

Als je echt een statische methode nodig hebt om deel uit te maken van de klas, kun je de gebruiken staticmethoddecorateur.


Antwoord 8

Dus, statische methoden zijn de methoden die kunnen worden aangeroepen zonder het object van een klasse te maken.
Bijvoorbeeld:-

   @staticmethod
    def add(a, b):
        return a + b
b = A.add(12,12)
print b

In de bovenstaande voorbeeldmethode wordt addaangeroepen door de klassenaam Aen niet door de objectnaam.


Antwoord 9

Ik kom deze vraag van tijd tot tijd tegen. De use case en het voorbeeld waar ik dol op ben is:

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

Het heeft geen zin om een object van de klasse cmath te maken, omdat er geen status is in een cmath-object. cmath is echter een verzameling methoden die allemaal op de een of andere manier gerelateerd zijn. In mijn voorbeeld hierboven werken alle functies in cmath op de een of andere manier op complexe getallen.


Antwoord 10

Python Static-methoden kunnen op twee manieren worden gemaakt.

  1. Statische methode() gebruiken

    class Arithmetic:
        def add(x, y):
            return x + y
    # create add static method
    Arithmetic.add = staticmethod(Arithmetic.add)
    print('Result:', Arithmetic.add(15, 10))
    

Uitvoer:

Resultaat: 25

  1. @staticmethod gebruiken

    class Arithmetic:
    # create add static method
    @staticmethod
    def add(x, y):
        return x + y
    print('Result:', Arithmetic.add(15, 10))
    

Uitvoer:

Resultaat: 25

Other episodes