Pertanyaan Metode statis dengan Python?


Apakah mungkin untuk memiliki metode statis di Python sehingga saya dapat memanggil mereka tanpa menginisialisasi kelas, seperti:

ClassName.StaticMethod ( )

1391
2018-04-09 21:23


asal


Jawaban:


Ya, menggunakan metode statis penghias

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print x

MyClass.the_static_method(2) # outputs 2

Perhatikan bahwa beberapa kode mungkin menggunakan metode lama mendefinisikan metode statis, menggunakan staticmethod sebagai fungsi daripada dekorator. Ini hanya boleh digunakan jika Anda harus mendukung versi kuno Python (2.2 dan 2.3)

class MyClass(object):
    def the_static_method(x):
        print x
    the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2) # outputs 2

Ini sepenuhnya identik dengan contoh pertama (menggunakan @staticmethod), hanya tidak menggunakan sintaks dekorator yang bagus

Akhirnya, gunakan staticmethod() hemat! Ada beberapa situasi di mana metode statis diperlukan dalam Python, dan saya telah melihatnya digunakan berkali-kali di mana fungsi "tingkat atas" terpisah akan lebih jelas.


Berikut ini adalah kata demi kata dari dokumentasi::

Metode statis tidak menerima argumen pertama implisit. Untuk mendeklarasikan metode statis, gunakan idiom ini:

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

Bentuk @staticmethod adalah fungsi penghias - lihat deskripsi definisi fungsi di Definisi fungsi untuk detailnya.

Ini bisa disebut baik di kelas (seperti C.f()) atau pada suatu instance (seperti C().f()). Instance ini diabaikan kecuali untuk kelasnya.

Metode statis dalam Python mirip dengan yang ditemukan di Java atau C ++. Untuk konsep yang lebih maju, lihat classmethod().

Untuk informasi lebih lanjut tentang metode statis, lihat dokumentasi pada hirarki tipe standar di Hirarki tipe standar.

Baru dalam versi 2.2.

Berubah dalam versi 2.4: Sintaks dekorator fungsi ditambahkan.


1696
2018-04-09 21:24



Saya pikir itu Steven sebenarnya benar. Untuk menjawab pertanyaan asli, kemudian, untuk mengatur metode kelas, anggap saja bahwa argumen pertama tidak akan menjadi contoh panggilan, dan kemudian pastikan bahwa Anda hanya memanggil metode dari kelas.

(Perhatikan bahwa jawaban ini mengacu pada Python 3.x. Dalam Python 2.x Anda akan mendapatkan TypeError untuk memanggil metode di kelas itu sendiri.)

Sebagai contoh:

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)

Dalam kode ini, metode "rollCall" mengasumsikan bahwa argumen pertama bukan sebuah instance (seperti yang akan terjadi jika dipanggil oleh instance, bukan kelas). Selama "rollCall" dipanggil dari kelas alih-alih instance, kode akan berfungsi dengan baik. Jika kami mencoba memanggil "rollCall" dari instance, misalnya:

rex.rollCall(-1)

Namun, itu akan menyebabkan pengecualian untuk dibangkitkan karena akan mengirim dua argumen: itu sendiri dan -1, dan "rollCall" hanya didefinisikan untuk menerima satu argumen.

Kebetulan, rex.rollCall () akan mengirim jumlah argumen yang benar, tetapi juga akan menyebabkan pengecualian untuk dibangkitkan karena sekarang n akan mewakili contoh Dog (yaitu, rex) ketika fungsi mengharapkan n menjadi numerik.

Di sinilah dekorasi datang di: Jika kita mengawali metode "rollCall" dengan

@staticmethod

kemudian, dengan menyatakan secara eksplisit bahwa metode ini statis, kita bahkan dapat memanggilnya dari sebuah instance. Sekarang,

rex.rollCall(-1)

akan bekerja. Penyisipan @staticmethod sebelum definisi metode, kemudian, menghentikan instance dari mengirim dirinya sebagai argumen.

Anda dapat memverifikasi ini dengan mencoba kode berikut dengan dan tanpa baris @staticShhod yang dikomentari.

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)

176
2018-04-18 09:16



Ya, periksa metode statis penghias:

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

74
2018-04-09 21:24



Anda tidak benar-benar perlu menggunakan @staticmethod penghias. Hanya mendeklarasikan sebuah metode (yang tidak mengharapkan parameter diri) dan memanggilnya dari kelas. Dekorator hanya ada di sana jika Anda ingin dapat memanggilnya dari sebuah instance juga (yang bukan apa yang ingin Anda lakukan)

Sebagian besar, Anda hanya menggunakan fungsi ...


43
2018-04-10 16:00



Metode statis dengan Python?

Apakah mungkin untuk memiliki metode statis dengan Python sehingga saya bisa memanggil mereka   tanpa menginisialisasi kelas, seperti:

ClassName.StaticMethod()

Ya, metode statis dapat dibuat seperti ini (meskipun sedikit lebih banyak Pythonic untuk menggunakan garis bawah, bukan CamelCase untuk metode):

class ClassName(object):

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

Di atas menggunakan sintaks dekorator. Sintaks ini setara dengan

class ClassName(object):

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

    static_method = staticmethod(static_method)

Ini dapat digunakan seperti yang Anda gambarkan:

ClassName.static_method()

Contoh yang dibangun dari metode statis adalah str.maketrans() dengan Python 3, yang merupakan fungsi dalam string modul dengan Python 2.


Pilihan lain yang dapat digunakan saat Anda mendeskripsikan adalah classmethodperbedaannya adalah bahwa classmethod mendapatkan kelas sebagai argumen pertama implisit, dan jika subclass, maka ia mendapat subclass sebagai argumen pertama yang implisit.

class ClassName(object):

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

Perhatikan itu cls bukan nama yang diperlukan untuk argumen pertama, tetapi sebagian besar coders Python berpengalaman akan menganggapnya buruk dilakukan jika Anda menggunakan yang lain.

Ini biasanya digunakan sebagai konstruktor alternatif.

new_instance = ClassName.class_method()

Contoh yang dibangun adalah dict.fromkeys():

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

28
2018-01-24 04:34



Selain kekhasan bagaimana caranya objek metode statis berperilaku, ada jenis kecantikan tertentu yang dapat Anda gunakan saat mengatur kode level modul Anda.

# 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

Sekarang menjadi sedikit lebih intuitif dan mendokumentasikan diri di mana konteks komponen-komponen tertentu yang dimaksudkan untuk digunakan dan itu idealnya ideal untuk penamaan kasus uji yang berbeda serta memiliki pendekatan langsung ke bagaimana modul tes memetakan ke modul yang sebenarnya di bawah tes untuk puris .

Saya sering merasa layak untuk menerapkan pendekatan ini untuk mengatur kode utilitas proyek. Cukup sering, orang segera bergegas dan membuat utils paket dan berakhir dengan 9 modul yang satu memiliki 120 LOC dan sisanya dua lOC terbaik. Saya lebih memilih untuk memulai dengan ini dan mengubahnya menjadi paket dan membuat modul hanya untuk binatang yang benar-benar layak mendapatkannya:

# 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

9
2017-12-29 19:47



Mungkin opsi yang paling sederhana adalah hanya menempatkan fungsi-fungsi itu di luar kelas:

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"

Dengan menggunakan metode ini, fungsi yang memodifikasi atau menggunakan status objek internal (memiliki efek samping) dapat disimpan di kelas, dan fungsi utilitas yang dapat digunakan kembali dapat dipindahkan ke luar.

Katakanlah file ini dipanggil dogs.py. Untuk menggunakan ini, Anda akan menelepon dogs.barking_sound() dari pada dogs.Dog.barking_sound.

Jika Anda benar-benar membutuhkan metode statis untuk menjadi bagian dari kelas, Anda dapat menggunakan metode statis penghias.


7
2017-07-30 16:10



Saya menemukan pertanyaan ini dari waktu ke waktu. Contoh penggunaan dan contoh yang saya sukai adalah:

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']
>>> 

Tidak masuk akal untuk membuat objek dari kelas cmath, karena tidak ada keadaan dalam objek cmath. Namun, cmath adalah kumpulan metode yang semuanya terkait dalam beberapa cara. Dalam contoh saya di atas, semua fungsi dalam cmath bertindak pada bilangan kompleks dalam beberapa cara.


-1
2018-01-08 06:53