python3.x - Python 如何通过类方法创建实例方法?
PHPz
PHPz 2017-04-17 17:53:52
0
2
971

下面是 Python 3.x language reference 中的一段话,大意是理解的,不过写不出一个这样的示例,求大神给个与这段话一致的示例:

When an instance method object is derived from a class method object, the “class instance” stored in self will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.

PHPz
PHPz

学习是最好的投资!

membalas semua(2)
黄舟

Sebenarnya, anda akan memahami bahagian ini dengan melakukan eksperimen anda sendiri.


Mari kita mulakan daripada teks asal dan bahagikannya kepada dua perenggan untuk dibincangkan Perenggan pertama berkata:

Apabila objek kaedah contoh dipanggil, fungsi asas (__func__) dipanggil, memasukkan contoh kelas (__self__) di hadapan senarai argumen Contohnya, apabila C ialah kelas yang mengandungi definisi untuk fungsi f(), dan x ialah kejadian C, memanggil x.f(1) bersamaan dengan memanggil C.f(x, 1).

Perenggan pertama artikel asal mengatakan bahawa apabila instance method object dipanggil, parameter pertama __func__ digantikan dahulu dengan class instance dan kemudian dipanggil, dan kemudian memberikan contoh:

x.f(1) == C.f(x,1)  # x is an instance of C

Kami menggunakan contoh berikut untuk menggambarkan Di sini kami mempunyai kelas Demo, yang mempunyai fungsi foo dan fungsi bar di bawahnya.

DemoKategori:

class Demo:

    def foo(self, *args):
        return 'Call foo by instance' + repr(self) + 'with args' + repr(args)

    @classmethod
    def bar(cls, *args):
        return 'Call bar by class ' + repr(cls) + 'with args' + repr(args)

Sebenarnya:

  1. Python untuk foo akan menjana fungsi am, yang akan dirujuk oleh Demo.foo.

  2. Apabila kita menulis demo.foo, Python akan serta-merta mencipta objek kaedah terikat: demo.foo Objek kaedah ini adalah kaedah terikat untuk mengikat contoh demo, jadi demo.foo.__self__ akan merujuk kepada demo dan Python juga akan merekodkan Demo.foo dalam demo.foo.__func__.

  3. Jadi apabila demo.foo ini dipanggil (demo.foo(1,2,3)), ia sebenarnya akan memanggil demo.foo.__func__ dan menggunakan demo.foo.__self__ (sebenarnya demo itu sendiri) sebagai parameter pertama.

Jika ditunjukkan menggunakan kelas yang kami tulis, contohnya menjadi:

   x.f(1)   ==    C.f(x, 1) 
demo.foo(1) == Demo.foo(demo, 1) == demo.foo.__func__(demo.foo.__self__, 1) 

Lihat kod:

demo  = Demo()

print('=== Demo start ===\n')

print('demo.foo', ':', demo.foo)
print('    [type             ] ', type(demo.foo))
print('    [demo.foo.__self__] ', demo.foo.__self__)
print('    [demo.foo.__func__] ', demo.foo.__func__)
print('    [demo.foo(1,2,3)  ] ', demo.foo(1,2,3))
print()

print('Demo.foo', ':', Demo.foo)
print('    [type                 ] ', type(Demo.foo))
print('    [Demo.foo(demo, 1,2,3)] ', Demo.foo(demo, 1,2,3))
print()

print('demo.foo.__func__', ':',  demo.foo.__func__,)
print('    [type                          ] ', type(demo.foo.__func__))
print('    [demo.foo.__func__(demo, 1,2,3)] ', demo.foo.__func__(demo, 1,2,3))
print()

print('Demo.foo is demo.foo.__func__ --> ', Demo.foo is demo.foo.__func__)

Keputusan ujian:

=== Demo start ===

demo.foo : <bound method Demo.foo of <__main__.Demo object at 0x7f413db47fd0>>
    [type             ]  <class 'method'>
    [demo.foo.__self__]  <__main__.Demo object at 0x7f413db47fd0>
    [demo.foo.__func__]  <function Demo.foo at 0x7f413db41840>
    [demo.foo(1,2,3)  ]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

Demo.foo : <function Demo.foo at 0x7f413db41840>
    [type                 ]  <class 'function'>
    [Demo.foo(demo, 1,2,3)]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

demo.foo.__func__ : <function Demo.foo at 0x7f413db41840>
    [type                          ]  <class 'function'>
    [demo.foo.__func__(demo, 1,2,3)]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

Demo.foo is demo.foo.__func__ -->  True

Baca perenggan kedua:

Apabila objek kaedah contoh diterbitkan daripada objek kaedah kelas, "contoh kelas" yang disimpan dalam diri sebenarnya akan menjadi kelas itu sendiri, supaya memanggil sama ada x.f(1) atau C.f(1) adalah bersamaan dengan memanggil f(C,1) dengan f ialah fungsi asas.

Idea utama perenggan kedua ialah apabila objek kaedah contoh datang daripada objek kaedah kelas, selfcontoh kelas yang wujud dalam akan menjadi kelas sendiri, dan kemudian Contoh lain:

x.f(1) == C.f(1) == f(C,1)  # x is an instance of C

Kami juga menggunakan contoh untuk menggambarkan:

  1. Python akan menjana Demo.bar untuk bar, iaitu objek kaedah terikat daripada objek kaedah kelas Pada asalnya, Demo.bar adalah seperti Demo.foo Ia juga merupakan fungsi Python umum, tetapi melalui penghias (@classmethod penghias), ia menjadi objek kaedah terikat Jika anda ingin memerhati fungsi umum asal, anda hanya boleh melihatnya dalam Demo.bar.__func__. ia terikat Demo kelas, jadi Demo.bar.__self__ akan merujuk kepada kelas Demo.

  2. Jadi apabila Demo.bar dipanggil (Demo.bar(1)), dia sebenarnya akan memanggil Demo.bar.__func__ dan menggunakan Demo.bar.__self__ (sebenarnya Demo dirinya) sebagai parameter pertama.

Jika ditunjukkan menggunakan kelas yang kami tulis, contohnya menjadi:

   x.f(1)   ==    C.f(1)   == f(C, 1)
demo.bar(1) == Demo.bar(1) == Demo.bar.__func__(Demo, 1) == Demo.bar.__func__(Demo.bar.__self__, 1) 

Kod ujian:

demo  = Demo()

print('=== Demo start ===\n')

print('Demo.bar', ':', Demo.bar)
print('    [type             ] ', type(Demo.bar))
print('    [Demo.bar.__self__] ', Demo.bar.__self__)
print('    [Demo.bar.__func__] ', Demo.bar.__func__)
print('    [Demo.bar(1,2,3)  ] ', Demo.bar(1,2,3))
print()

print('Demo.bar(1)               ', Demo.bar(1))
print('demo.bar(1)               ', demo.bar(1))
print('Demo.bar.__func__(Demo, 1)', Demo.bar.__func__(Demo, 1))

Keputusan ujian:

=== Demo start ===

Demo.bar : <bound method type.bar of <class '__main__.Demo'>>
    [type             ]  <class 'method'>
    [Demo.bar.__self__]  <class '__main__.Demo'>
    [Demo.bar.__func__]  <function Demo.bar at 0x7f413db41950>
    [Demo.bar(1,2,3)  ]  Call bar by class <class '__main__.Demo'>with args(1, 2, 3)

Demo.bar(1)                Call bar by class <class '__main__.Demo'>with args(1,)
demo.bar(1)                Call bar by class <class '__main__.Demo'>with args(1,)
Demo.bar.__func__(Demo, 1) Call bar by class <class '__main__.Demo'>with args(1,)

Kesimpulan:

  1. Dalam Python3, terdapat dua jenis fungsi dalam kelas, satu ialah objek fungsi umum, dan satu lagi ialah objek kaedah terikat

  2. Kaedah instance ialah objek kaedah yang terdiri daripada fungsi umum yang terikat pada contoh, dan mehtod kelas ialah objek kaedah yang terdiri daripada fungsi umum yang terikat kepada kelas

  3. Apabila
  4. kaedah terikat dipanggil, ia sebenarnya memanggil fungsi asal (dirakam dalam __func__), tetapi objek terikat akan digunakan sebagai parameter pertama (dirakam dalam __self__) .


Rujukan:

Perbezaan antara kaedah dan fungsi
Perbezaan cara untuk mencipta objek kaedah contoh dalam Python

大家讲道理
# -*- coding: utf-8 -*-


class Parent:
    @classmethod
    # 这里就相当于是f
    def foo(cls, arg):
        print("foo called, " + str(cls) + " " + str(arg))


class Child(Parent):
    pass

# 创建一个子类的实例
a = Child()
# 调用类方法,可见将对象传递给类方法时,会调用类方法,并且自动绑定了类
a.foo(1)
# 结果和上述一样
Child.foo(1)
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan