ฉันรู้จักวิธีการเสมือนจริงจาก PHP หรือ Java
จะนำไปใช้ใน Python ได้อย่างไร?
หรือฉันต้องกำหนดวิธีการว่างเปล่าในคลาสนามธรรมแล้วลบล้าง?
ฉันรู้จักวิธีการเสมือนจริงจาก PHP หรือ Java
จะนำไปใช้ใน Python ได้อย่างไร?
หรือฉันต้องกำหนดวิธีการว่างเปล่าในคลาสนามธรรมแล้วลบล้าง?
คำตอบ:
แน่นอนและคุณไม่จำเป็นต้องกำหนดวิธีการในคลาสพื้นฐาน ในหลามวิธีการที่ดีกว่าเสมือน - พวกเขากำลังแบบไดนามิกอย่างสมบูรณ์การพิมพ์ในหลามเป็นเป็ดพิมพ์
class Dog:
def say(self):
print "hau"
class Cat:
def say(self):
print "meow"
pet = Dog()
pet.say() # prints "hau"
another_pet = Cat()
another_pet.say() # prints "meow"
my_pets = [pet, another_pet]
for a_pet in my_pets:
a_pet.say()
Cat
และDog
ใน Python ไม่จำเป็นต้องได้มาจากคลาสพื้นฐานทั่วไปเพื่ออนุญาตพฤติกรรมนี้ - คุณจะได้รับมันฟรี ที่กล่าวว่าโปรแกรมเมอร์บางคนชอบที่จะกำหนดลำดับชั้นของชั้นเรียนของตนในทางที่เข้มงวดมากขึ้นเพื่อจัดทำเอกสารได้ดีและกำหนดบางเข้มงวดของการพิมพ์ นอกจากนี้ยังเป็นไปได้ - ดูตัวอย่างโมดูลมาตรฐานabc
raise NotImplementedError()
นี่เป็นข้อยกเว้นที่แนะนำในการเพิ่ม "วิธีการเสมือนจริง" ของคลาสพื้นฐาน "นามธรรม" ที่ไม่ใช้วิธีการ
https://docs.python.org/3.5/library/exceptions.html#NotImplementedErrorพูดว่า:
RuntimeError
ข้อยกเว้นนี้ได้มาจาก ในคลาสพื้นฐานที่ผู้ใช้กำหนดเมธอดนามธรรมควรเพิ่มข้อยกเว้นนี้เมื่อต้องการคลาสที่สืบทอดมาเพื่อแทนที่เมธอด
ดังที่คนอื่น ๆ กล่าวไว้ส่วนใหญ่เป็นเอกสารประกอบและไม่จำเป็น แต่วิธีนี้คุณจะได้รับข้อยกเว้นที่มีความหมายมากกว่าข้อผิดพลาดของแอตทริบิวต์ที่ขาดหายไป
เช่น:
class Base(object):
def virtualMethod(self):
raise NotImplementedError()
def usesVirtualMethod(self):
return self.virtualMethod() + 1
class Derived(Base):
def virtualMethod(self):
return 1
print Derived().usesVirtualMethod()
Base().usesVirtualMethod()
ให้:
2
Traceback (most recent call last):
File "./a.py", line 13, in <module>
Base().usesVirtualMethod()
File "./a.py", line 6, in usesVirtualMethod
return self.virtualMethod() + 1
File "./a.py", line 4, in virtualMethod
raise NotImplementedError()
NotImplementedError
ที่เกี่ยวข้อง: สามารถสร้างคลาสนามธรรมใน Python ได้หรือไม่?
วิธีการ Python เป็นเสมือนจริงเสมอ
จริงๆแล้วในเวอร์ชัน 2.6 python มีสิ่งที่เรียกว่าคลาสพื้นฐานแบบนามธรรมและคุณสามารถตั้งค่าวิธีการเสมือนอย่างชัดเจนได้ดังนี้:
from abc import ABCMeta
from abc import abstractmethod
...
class C:
__metaclass__ = ABCMeta
@abstractmethod
def my_abstract_method(self, ...):
มันทำงานได้ดีมากหากคลาสนั้นไม่ได้รับมรดกจากคลาสที่ใช้เมตาคลาสสิกอยู่แล้ว
แหล่งที่มา: http://docs.python.org/2/library/abc.html
วิธีการ Python เป็นเสมือนจริงเสมอ
เช่นเดียวกับที่อิกนาซิโอกล่าว แต่การสืบทอดคลาสอาจเป็นแนวทางที่ดีกว่าในการนำสิ่งที่คุณต้องการไปใช้
class Animal:
def __init__(self,name,legs):
self.name = name
self.legs = legs
def getLegs(self):
return "{0} has {1} legs".format(self.name, self.legs)
def says(self):
return "I am an unknown animal"
class Dog(Animal): # <Dog inherits from Animal here (all methods as well)
def says(self): # <Called instead of Animal says method
return "I am a dog named {0}".format(self.name)
def somethingOnlyADogCanDo(self):
return "be loyal"
formless = Animal("Animal", 0)
rover = Dog("Rover", 4) #<calls initialization method from animal
print(formless.says()) # <calls animal say method
print(rover.says()) #<calls Dog says method
print(rover.getLegs()) #<calls getLegs method from animal class
ผลลัพธ์ควรเป็น:
I am an unknown animal
I am a dog named Rover
Rover has 4 legs
สิ่งที่เหมือนกับวิธีเสมือนใน C ++ (การเรียกใช้เมธอดของคลาสที่ได้รับผ่านการอ้างอิงหรือตัวชี้ไปยังคลาสพื้นฐาน) ไม่สมเหตุสมผลใน Python เนื่องจาก Python ไม่มีการพิมพ์ (ฉันไม่รู้ว่าวิธีการเสมือนทำงานอย่างไรใน Java และ PHP)
แต่ถ้าโดย "เสมือน" คุณหมายถึงการเรียกใช้งานด้านล่างสุดในลำดับชั้นการสืบทอดนั่นคือสิ่งที่คุณจะได้รับใน Python เสมอเนื่องจากคำตอบหลาย ๆ คำตอบชี้ให้เห็น
ดีเกือบตลอดเวลา ...
ตามที่ dplamp ชี้ให้เห็นไม่ใช่ทุกวิธีใน Python ที่ทำงานเช่นนั้น วิธี Dunder ไม่ และฉันคิดว่านั่นเป็นคุณสมบัติที่ไม่ค่อยเป็นที่รู้จัก
ลองพิจารณาตัวอย่างเทียมนี้
class A:
def prop_a(self):
return 1
def prop_b(self):
return 10 * self.prop_a()
class B(A):
def prop_a(self):
return 2
ตอนนี้
>>> B().prop_b()
20
>>> A().prob_b()
10
อย่างไรก็ตามลองพิจารณาสิ่งนี้
class A:
def __prop_a(self):
return 1
def prop_b(self):
return 10 * self.__prop_a()
class B(A):
def __prop_a(self):
return 2
ตอนนี้
>>> B().prop_b()
10
>>> A().prob_b()
10
สิ่งเดียวที่เราเปลี่ยนแปลงคือการสร้างprop_a()
วิธีการดักฟัง
ปัญหาที่มีลักษณะการทำงานที่แรกที่สามารถเป็นไปได้ว่าคุณจะไม่สามารถเปลี่ยนพฤติกรรมของในชั้นเรียนมาโดยไม่ส่งผลกระทบต่อการทำงานของprop_a()
คำพูดที่ดีมากโดย Raymond Hettinger ยกตัวอย่างกรณีการใช้งานที่ไม่สะดวกprop_b()