【问题标题】:Problems with "F" and brackets“F”和括号的问题
【发布时间】:2021-08-27 20:41:24
【问题描述】:

我正在尝试从 Sentdex 的视频中了解 matplotlib 教程的一些语法。例如,在第 10 行,什么是“F(container, self)”,在这种情况下 F 是什么?第 11 行的“self.Frames[F]”也是如此,这里的 F 是什么,为什么左侧有方括号?最后,第 15 行也是一样,为什么 [cont] 有方括号?

class SeaofBTCapp(tk.Tk):                                                                   
    def __init__(self, *args, **kwargs):
    tk.Tk.__init__(self, *args, **kwargs)
    container = tk.Frame(self)

    container.pack(side="top", fill="both", expand = True)

    container.grid_rowconfigure(0, weight=1)
    container.grid_columnconfigure(0, weight=1)

    self.frames = {}

    for F in (StartPage, PageOne, PageTwo):

        frame = F(container, self)

        self.frames[F] = frame

        frame.grid(row=0, column=0, sticky="nsew")

    self.show_frame(StartPage)

def show_frame(self, cont):

    frame = self.frames[cont]
    frame.tkraise()

【问题讨论】:

  • F 是您在(StartPage, PageOne, PageTwo) 迭代中的当前项目
  • 那你在做StartPage(container, self), PageOne(container, self), PageTwo(container, self)
  • 虽然使用某个类或其他任何东西作为字典的键很奇怪...

标签: python


【解决方案1】:

函数、类和类(对象)的实例都是 Python 中的第一类。 F() 只调用了F,如果F 不可调用(What is a "callable"?)会抛出异常。 [F] 使用 F 作为字典 self.frames 中的键([] 也可以以其他方式使用: https://docs.python.org/3/reference/expressions.html#index-41) 将抛出异常,除非 F 是可散列的并且支持 __eq__ 方法。大概所有的 StartPage、PageOne 和 PageTwo 都是可调用的、可散列的,并且有一个 __eq__ 方法。

也许使代码更通用将有助于澄清事情:

#!/usr/bin/env python3

class frame:
    def __init__(self, *args):
        print(f"frame initialized with {args}")
    def grid(self, **kwargs):
        print(f"frame.grid called with args: {kwargs}")


def StartPage(a=None, b=None):
    return frame(a, b)

class PageOne:
    def __init__(self, *args):
        print(f"PageOne initialized with {args}")
    def grid(self, **kwargs):
        print(f"PageOne.grid called with args: {kwargs}")

class C:
    def __call__(*args):
        return PageOne(args)

PageTwo = C()
container = None

frames = {}
for F in (StartPage, PageOne, PageTwo):
    frame = F(container, None)
    frames[F] = frame
    print( f"F is {F}")
    frame.grid(row=0, column=0, sticky="nsew")

上面的代码产生了输出:

frame initialized with (None, None)
F is <function StartPage at 0x105c63f70>
frame.grid called with args: {'row': 0, 'column': 0, 'sticky': 'nsew'}
PageOne initialized with (None, None)
F is <class '__main__.PageOne'>
PageOne.grid called with args: {'row': 0, 'column': 0, 'sticky': 'nsew'}
PageOne initialized with ((<__main__.C object at 0x105e2a610>, None, None),)
F is <__main__.C object at 0x105e2a610>
PageOne.grid called with args: {'row': 0, 'column': 0, 'sticky': 'nsew'}

在这种情况下,我们将循环遍历 3 次。第一次在循环中,名称F 绑定到函数StartPage。函数是可调用的; F(container, None) 使用这两个参数调用函数 StartPage 并将 frame 绑定到该函数调用返回的对象。该对象有一个grid 方法,frame.grid() 调用它。 StartPage 是可散列的并且支持__eq__ 方法,因此它可以用作frames 字典中的键。第二次通过循环,名称F 被匹配到类PageOne,并且F(container, None) 调用类的__init__ 方法来创建一个作为该类实例的对象。同样,该对象是可散列的,可以用作frames 字典中的键,它包含grid 方法。第三次通过循环,名称 F 绑定到对象 PageTwo,该对象先前被初始化为类 C 的实例。

在您的情况下,迭代中的所有三个对象可能都是同一个类的实例,但我希望具体示例有助于澄清。

【讨论】:

  • 您好,感谢您在这件事上“牵着我的手”的善意和体贴的帮助。但是,我仍然对您的解释有一些疑问: 1. 当我没有像“def F():”那样事先将 F 声明为函数时,我仍然认为 F 在这里充当循环计数器吗? 2、为什么PageTwo在第三次循环时突然初始化了三个参数,一个是它的地址? 3. eq 方法与作为函数调用有什么关系?抱歉我的问题,因为我还是 Python 的新手。
  • F 只是一个用作循环索引的变量。每次通过循环,它都会采用不同的值。第一次通过时,名称F 绑定到StartPage。我不知道您的代码中 StartPage 的类型是什么。在我的示例中,它是一个函数。对象方法接收对象作为第一个参数,因此AnObject.method(b,c)AnObject 作为其第一个参数调用函数,bc 作为其第二个和第三个参数。按照惯例,第一个参数通常命名为self__eq__ 方法与函数无关。
  • __eq__ 是一个技术细节:在字典中用作键的任何对象都必须支持__eq__ 方法。您可以在 docs.python.org/3/glossary.html#term-hashablestackoverflow.com/questions/1608842/…stackoverflow.com/questions/14535730/… 阅读更多相关信息
猜你喜欢
  • 2019-07-31
  • 2019-06-28
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多