ความมหัศจรรย์ใหม่super()
พฤติกรรมถูกเพิ่มเข้ามาเพื่อหลีกเลี่ยงการละเมิดแห้ง (ไม่ซ้ำตัวเอง) หลักการดูPEP 3135 การตั้งชื่อชั้นเรียนอย่างชัดเจนโดยการอ้างอิงว่าเป็นโกลบอลก็มีแนวโน้มที่จะมีปัญหาเรื่องการตอบโต้แบบเดียวกันกับที่คุณค้นพบด้วยsuper()
ตัวเอง:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
เช่นเดียวกับการใช้ class decorators ซึ่ง decorator ส่งคืนออบเจ็กต์ใหม่ซึ่ง rebinds ชื่อคลาส:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
super()
__class__
เซลล์เวทย์มนตร์ก้าวเท้าลงปัญหาเหล่านี้เป็นอย่างดีโดยให้คุณเข้าถึงวัตถุคลาสดั้งเดิม
PEP ถูกเตะออกโดยกุยซึ่งตอนแรกคาดว่าsuper
จะกลายเป็นคำหลักและความคิดในการใช้เซลล์เพื่อค้นหาชั้นเรียนปัจจุบันก็เป็นของเขาเช่นกัน แน่นอนความคิดที่จะทำให้มันเป็นคำหลักที่เป็นส่วนหนึ่งของร่างแรกของห้าวหาญ
อย่างไรก็ตามในความเป็นจริงกุยโด้เองก็ก้าวออกมาจากแนวคิดคำหลักว่า 'มีมนต์ขลังมาก'โดยเสนอให้มีการใช้งานปัจจุบันแทน เขาคาดว่าการใช้ชื่ออื่นsuper()
อาจเป็นปัญหา :
แพทช์ของฉันจะใช้วิธีการแก้ปัญหาระดับกลาง: จะอนุมานว่าคุณต้องการเมื่อใดก็ตามที่คุณใช้ชื่อตัวแปร__class__
'super'
ดังนั้นหากคุณ (ทั่วโลก) เปลี่ยนชื่อsuper
เป็นsupper
และใช้supper
แต่ไม่super
ทำงานมันจะไม่ทำงานหากไม่มีข้อโต้แย้ง (แต่จะยังคงใช้งานได้หากคุณผ่านมัน
__class__
หรือวัตถุคลาสจริง); หากคุณมีชื่อตัวแปรที่ไม่เกี่ยวข้องsuper
สิ่งต่าง ๆ จะใช้งานได้ แต่วิธีการจะใช้เส้นทางการโทรที่ช้ากว่าเล็กน้อยที่ใช้สำหรับตัวแปรเซลล์
ดังนั้นในท้ายที่สุด Guido เองก็ประกาศว่าการใช้super
คำหลักนั้นไม่ถูกต้องและการจัดหา__class__
เซลล์เวทย์มนตร์เป็นการประนีประนอมที่ยอมรับได้
ฉันยอมรับว่าเวทมนตร์พฤติกรรมโดยปริยายของการใช้งานนั้นค่อนข้างน่าแปลกใจ แต่super()
เป็นหนึ่งในฟังก์ชั่นที่ใช้ผิดพลาดมากที่สุดในภาษา เพียงแค่ดูความผิดพลาดsuper(type(self), self)
หรือsuper(self.__class__, self)
การเรียกใช้ที่พบในอินเทอร์เน็ต ถ้ามีของรหัสที่เคยถูกเรียกจากชั้นเรียนมาคุณจะจบลงด้วยการยกเว้นการเรียกซ้ำอนันต์ อย่างน้อยที่สุดง่ายขึ้นsuper()
โทรโดยไม่ขัดแย้งหลีกเลี่ยงว่าปัญหาที่เกิดขึ้น
สำหรับการเปลี่ยนชื่อsuper_
; เพียงอ้างอิง__class__
ในวิธีการของคุณเช่นกันและมันจะทำงานอีกครั้ง เซลล์ถูกสร้างขึ้นหากคุณอ้างอิงsuper
หรือ __class__
ชื่อในวิธีการของคุณ:
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping