子类tkinter中的super()在python中不起作用
我有一个类,叫做 Application,它有两个子类,分别是 MyButton 和 MyLabel。Application 里面还有一些东西
self.backgroundcolor = 'orange'
self.textcolor = 'black'
我想在我的子类 MyButton 和 MyLabel 中使用这两个变量。所以,我试着这样做
class MyButton(Button):
def __init__(self, *args, **kwargs):
Button.__init__(self, *args, **kwargs)
self['bg'] = super(Application, self).backgroundcolor
self['fg'] = super(Application, self).textcolor
self['relief'] = FLAT
class MyLabel(Label):
def __init__(self, *args, **kwargs):
Label.__init__(self, *args, **kwargs)
self['fg'] = super(Application, self).textcolor
但是不行,系统提示说
TypeError: super(type, obj): obj must be an instance or subtype of type
不过我的 Application 类看起来是这样的
class Application(Frame):
global yearcal
def __init__(self, master=None):
Frame.__init__(self, master)
self.month = 5
self.year = 2014
self.color_clicked = 'lightskyblue'
now = datetime.datetime.now()
self.thisyear = now.year
self.thismonth = now.month
self.today = now.day
self.textcolor = 'purple'
self.bgcolor = 'gray'
self.today_color = 'palegreen1'
self.apt_color = 'light coral'
MORE STUFF HERE...
class MyButton(Button):
def __init__(self, *args, **kwargs):
Button.__init__(self, *args, **kwargs)
self['bg'] = super(Application, self).backgroundcolor
self['fg'] = super(Application, self).textcolor
self['relief'] = FLAT
class MyLabel(Label):
def __init__(self, *args, **kwargs):
Label.__init__(self, *args, **kwargs)
self['fg'] = super(Application, self).textcolor
4 个回答
在这个例子中,有些混淆了嵌套类和子类的概念。嵌套类是指在另一个类里面定义的类,而子类是通过扩展一个已有的类来定义的。
在Python中,类的继承(也就是super方法的基础)是通过定义一个类,并把父类作为参数来实现的:
class Application(Frame):
... #Some class definition
class MyButton(Application):
... #MyButton is now a subclass of Application.
但是这并不是你想要的,因为你希望你的
你最开始尝试使用嵌套类并不一定是个坏主意,因为这样可以把你类的所有行为整齐地放在一个地方,但它有一些严重的缺点,可能不是你想要的。
首先,你不能在嵌套类中引用
class Application(object):
classvar = "Foo" #This is a class level variable
class NestedClass(object):
#This is now a nested class, accessed using Application.NestedClass
def __init__(self, app):
#This will fail, classvar doesn't exist in this scope
self.var = classvar
#This will work if app is an instance of Application
#Or if app is the class itself
self.var = app.classvar
#This will always work, since it references the Application
#class directly but it won't capture changes introduced
#by an instance of Application, which is what you'll probably do
self.var = Application.classvar
由于作用域的问题,类级别的行为会变得非常混乱,而嵌套类则会更加混乱,因为没有什么好处是通过在模块级别实现每个类可以获得的。
处理这种需求的最好方法就是按照
在调用 super()
时,你需要传入你的 type
和“你自己”(self):
super(Application, self)
所以不要这样做:
super(MyButton, self)
因此出现了这个错误,obj 必须是 type 的实例或子类型
:
self
既不是 Application
的实例,也不是它的子类型。
我有一个类,叫做 Application,它有两个子类,分别是 MyButton 和 MyLabel。
MyButton
和 MyLabel
似乎并不是 Application
的子类。你只能通过 super()
来从子类访问 Application
。
比如,要让 MyLabel
成为 Application
的子类,可以这样做:
class MyLabel(Application):
def __init__(self, *args, **kwargs):
...
嵌套类不能直接访问外部类的属性。你需要通过间接的方式来访问,比如:
class Application(Frame):
global yearcal
def __init__(self, master=None):
Frame.__init__(self, master)
self.month = 5
self.year = 2014
self.color_clicked = 'lightskyblue'
now = datetime.datetime.now()
self.thisyear = now.year
self.thismonth = now.month
self.today = now.day
self.textcolor = 'purple'
self.bgcolor = 'gray'
self.today_color = 'palegreen1'
self.apt_color = 'light coral'
# create button and label and pass the application instance
# so that they can reference its attributes and methods
self.my_button = MyButton(self)
self.my_label = MyLabel(self)
class MyButton(Button):
def __init__(self, app_instance, *args, **kwargs):
Button.__init__(self, *args, **kwargs)
self['bg'] = app_instance.backgroundcolor
self['fg'] = app_instance.textcolor
self['relief'] = FLAT
class MyLabel(Label):
def __init__(self, app_instance, *args, **kwargs):
Label.__init__(self, *args, **kwargs)
self['fg'] = app_instance.textcolor