【发布时间】:2010-12-09 02:53:49
【问题描述】:
在 Python 中,如何从超类创建子类?
【问题讨论】:
-
请注意,Python 改变了您进行子类化的方式,因此有 2 种方式,它们不会混合使用。如果你混合,你会得到一个错误。阅读这篇文章以了解不同之处:stackoverflow.com/questions/1713038/…
在 Python 中,如何从超类创建子类?
【问题讨论】:
这是一个小代码:
# create a parent class
class Person(object):
def __init__(self):
pass
def getclass(self):
return 'I am a Person'
# create two subclass from Parent_class
class Student(Person):
def __init__(self):
super(Student, self).__init__()
def getclass(self):
return 'I am a student'
class Teacher(Person):
def __init__(self):
super(Teacher, self).__init__()
def getclass(self):
return 'I am a teacher'
person1 = Person()
print(person1.getclass())
student1 = Student()
print(student1.getclass())
teacher1 = Teacher()
print(teacher1.getclass())
显示结果:
I am a Person
I am a student
I am a teacher
【讨论】:
# Initialize using Parent
#
class MySubClass(MySuperClass):
def __init__(self):
MySuperClass.__init__(self)
或者,甚至更好的是,使用 Python 的内置函数 super()(参见 Python 2/Python 3 文档)可能是调用父级进行初始化的更好方法:
# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
def __init__(self):
super(MySubClassBetter, self).__init__()
或者,和上面一样,除了使用super()的零参数形式,它只在类定义中有效:
class MySubClassBetter(MySuperClass):
def __init__(self):
super().__init__()
【讨论】:
super,尤其是对于新的 Python 程序员(例如 Lutz)。我避免它。
super 的唯一原因是如果您不了解super 在Python 中的工作方式与super/parent 在其他语言中的工作方式之间的区别。诚然,这对于来自其他语言的人来说并不明显,但我不会得出结论,这有资格将其视为“谨慎”。它确实工作。它只是工作方式不同。在抱怨得到意想不到的结果之前,请先了解它在 Python 中的实际作用。
在上面的答案中,super 在没有任何(关键字)参数的情况下进行了初始化。但是,您通常希望这样做,并传递您自己的一些“自定义”参数。这是一个说明此用例的示例:
class SortedList(list):
def __init__(self, *args, reverse=False, **kwargs):
super().__init__(*args, **kwargs) # Initialize the super class
self.reverse = reverse
self.sort(reverse=self.reverse) # Do additional things with the custom keyword arguments
这是list 的子类,它在初始化时会立即按照reverse 关键字参数指定的方向对自身进行排序,如以下测试所示:
import pytest
def test_1():
assert SortedList([5, 2, 3]) == [2, 3, 5]
def test_2():
SortedList([5, 2, 3], reverse=True) == [5, 3, 2]
def test_3():
with pytest.raises(TypeError):
sorted_list = SortedList([5, 2, 3], True) # This doesn't work because 'reverse' must be passed as a keyword argument
if __name__ == "__main__":
pytest.main([__file__])
感谢 *args 到 super 的传递,列表可以初始化并填充项目,而不仅仅是空的。 (请注意,reverse 是符合 PEP 3102 的仅关键字参数)。
【讨论】:
class BankAccount:
def __init__(self, balance=0):
self.balance = int(balance)
def checkBalance(self): ## Checking opening balance....
return self.balance
def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
self.deposit_amount = deposit_amount
self.balance += deposit_amount
return self.balance
def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
return 'invalid transaction'
else:
self.balance -= withdraw_amount
return self.balance
class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class
def __init__(self,balance=0, minimum_balance=500):
BankAccount.__init__(self, balance=0)
self.minimum_balance = minimum_balance
self.balance = balance - minimum_balance
#print "Subclass MinimumBalanceAccount of the BankAccount class created!"
def MinimumBalance(self):
return self.minimum_balance
c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))
b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())
【讨论】:
class MySubClass(MySuperClass):
def __init__(self):
MySuperClass.__init__(self)
# <the rest of your custom initialization code goes here>
python 文档中的section on inheritance 更详细地解释了它
【讨论】:
__init__方法,否则无论如何都会使用原始的init方法(尽管值得一提,并且是完全有效的代码)
【讨论】:
还有另一种方法可以使用函数type()在python中动态创建子类:
SubClass = type('SubClass', (BaseClass,), {'set_x': set_x}) # Methods can be set, including __init__()
在处理元类时,您通常希望使用此方法。当您想做一些较低级别的自动化时,这会改变 python 创建类的方式。很可能您永远不需要以这种方式这样做,但是当您这样做时,您就会知道自己在做什么。
【讨论】:
一个英勇的小例子:
class SuperHero(object): #superclass, inherits from default object
def getName(self):
raise NotImplementedError #you want to override this on the child classes
class SuperMan(SuperHero): #subclass, inherits from SuperHero
def getName(self):
return "Clark Kent"
class SuperManII(SuperHero): #another subclass
def getName(self):
return "Clark Kent, Jr."
if __name__ == "__main__":
sm = SuperMan()
print sm.getName()
sm2 = SuperManII()
print sm2.getName()
【讨论】:
Python 中的子类化如下:
class WindowElement:
def print(self):
pass
class Button(WindowElement):
def print(self):
pass
这是一个关于 Python 的tutorial,其中还包含类和子类。
【讨论】:
class Mammal(object):
#mammal stuff
class Dog(Mammal):
#doggie stuff
【讨论】:
class Class1(object):
pass
class Class2(Class1):
pass
Class2 是 Class1 的子类
【讨论】:
class Subclass (SuperClass):
# Subclass stuff here
【讨论】: