tom*_*web 1 python oop tkinter
我开始学习PHP中的编程/ OOP。据我对PHP最佳实践的了解,如果不带任何参数,则可以实例化没有括号的类。
如
$class = new Class;
Run Code Online (Sandbox Code Playgroud)
相对于:
$class = new Class();
Run Code Online (Sandbox Code Playgroud)
我开始将自己的技能扩展到python中,并于昨天浪费了大约5个小时,试图弄清为什么一个函数即使简单得很简单也不会传递参数。我的代码:
class MainViewWidgets(MainViewContainer):
def __init__(self):
# instantiating like this prevents MainViewController.getHeaderItems from returning the arg passed to it, however the code still "works" in some sense
self.controller = MainViewController
#this works
self.controller = MainViewController()
def createHeaderOptionCheckbox(self, pane):
self.header_string = StringVar()
header_checkbox = ttk.Checkbutton(pane, text='Data Contains Headers', variable=self.header_string, onvalue='headers', offvalue='keys')
self.header_string.trace('w', self.headerOptionCheckboxChanged)
return header_checkbox
def headerOptionCheckboxChanged(self, *args):
print(self.header_string.get())
#will print "headers" or "keys" on checkbox toggle
print(self.controller.getHeaderItems(self.header_string.get()))
#prints "default"
class MainViewController:
def __init__(self):
self.CheckFile = CheckFile()
get_config = GetConfiguration('config.ini')
self.config_file = get_config.getProperty('directory', 'input_file')
self.csv = CSVReader(self.config_file)
self.chosen_index = None
def getHeaderItems(self, header='default'):
return header
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解为什么在Python中,即使没有以外的构造函数参数,也需要使用括号实例化一个类self。另外,为什么还要做MainViewController这种工作,但是却没有达到我想要的表现?就像在其中加载了函数一样,函数“完成了事情”,但似乎不接受参数。实例化没有括号的类有什么好处?
请注意,我不需要帮助来使此代码正常工作,我只想了解为什么会发生这种情况。
有人可以帮我理解为什么在Python中,即使self之外没有构造函数参数,也需要使用括号实例化一个类。
原因很简单:实例化对象时,实际上是在调用它的类(它本身是对象),然后使用调用对象()。
在python中,所有东西都是一流的对象,甚至类(和函数!)本身也是如此。为了使一个类成为第一类对象,需要遵循以下条件:该类需要使用自己的类(metaclass)来定义其行为。我们将类的类称为“元类”,以避免在谈论类和类的类时产生混淆。
回答问题的第二部分:当您使用MainViewController而不是MainViewController()因为它MainViewController 是一个成熟的对象(就像其他任何对象一样)时,发生了“事情” 。
因此,您可能会问:MainViewController对象的类是什么(实际上是元类)?
如您所知,您可以创建这样的类:
class MyClass:
pass
Run Code Online (Sandbox Code Playgroud)
注意,您可以通过这种方式创建相同的类。上面和下面之间没有什么区别:
MyClass = type('MyClass', (object,), {})
Run Code Online (Sandbox Code Playgroud)
该type元类是所有类的基元类。所有的python“新样式类”(我相信它们是在python 2.1中实现的,所以不再是“新”类)属于此类type:
print(type(MyClass)) # type
print(type(list)) # type
print(type(int)) # type
# Note that above, type is being used as a "function" (it's really just a callable)
Run Code Online (Sandbox Code Playgroud)
有趣的是,type它甚至是它自己的元类:
print(type(type)) # type
Run Code Online (Sandbox Code Playgroud)
重申一下:该类MyClass实际上是的实例化type。随之而来的是,调用该类将导致运行__call__其元类的方法。
当您这样做时:
obj = MyClass()
Run Code Online (Sandbox Code Playgroud)
...您正在调用 MyClass,导致(在后台)运行method type.__call__()。
所有用户定义的类都是这种情况,btw; 如果__call__在类中包含该方法,则该类是可调用的,并且在__call__调用类实例时将执行该方法:
class MyCallable():
def __call__(self):
print("You rang?")
my_instance = MyCallable()
my_instance() # You rang?
Run Code Online (Sandbox Code Playgroud)
您可以看到此操作。如果通过子类创建自己的元类type,则在创建基于自定义元类的类的实例时,可能会导致事情发生。例如:
class MyMeta(type):
def __call__(self, *args, **kwargs):
print "call: {} {} {}".format(self, args, kwargs)
return super().__call__(*args, **kwargs)
# Python 3:
class MyClass(metaclass = MyMeta):
pass
# Python 2:
class MyClass():
__metaclass__ = MyMeta
pass
Run Code Online (Sandbox Code Playgroud)
现在,当您这样做时MyClass(),您可以看到发生的__call__方法MyMeta先于其他任何事物(包括__new__AND和before __init__)。