简体   繁体   English

如何在 Python 中的嵌套 function 中调用 function

[英]How to call function in nested function in Python

I am just starting to learn programming.我刚开始学习编程。 I am trying to define a function in python so that I wouldn't have to repeat code in my program.我正在尝试在 python 中定义一个 function ,这样我就不必在我的程序中重复代码。 This program searches entries from database and displays either all entries or entries containing keyword.该程序从数据库中搜索条目并显示所有条目或包含关键字的条目。 Here is my program stripped down for the context of this question, that works as I intended:这是我为这个问题的上下文而精简的程序,它按我的意图工作:

from tkinter import *

import sqlite3
from tkinter import ttk
    

    root = Tk()
    root.title('Program')
    
    def search():
        search_window = Toplevel(root)
        search_window.title('Program - Search')
    def search_all():
        searchresult_window = Tk()
        searchresult_window.title('Program - Searchresult')

        #Checks the number of searchresults
        conn = sqlite3.connect('database.db')
        c = conn.cursor()
        c.execute('SELECT COUNT() FROM entry_table')
        number = int(str(c.fetchone()).replace(",","").replace("(","").replace(")",""));

        #Gets data from database
        c.execute('SELECT * FROM entry_table')
        data = c.fetchall()
        row_count = 0

        # Scrollbar
        main_frame = Frame(searchresult_window)
        main_frame.pack(fill=BOTH, expand=1)
        my_canvas = Canvas(main_frame)
        my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
        my_scroblbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
        my_scroblbar.pack(side=RIGHT, fill=Y)
        my_canvas.configure(yscrollcommand=my_scroblbar.set)
        my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
        seccond_frame = Frame(my_canvas)
        my_canvas.create_window((0, 0), window=seccond_frame, anchor="nw")

        # Displays searchresults on screen
        for _ in range(number):
            searchresult_frame = LabelFrame(seccond_frame, pady=5, bg='yellow1')
            searchresult_frame.pack()
            data_label = Label(hakutulos_frame, text=data[row_count][1], borderwidth=5, relief="groove", width=10)
            data_label.grid(row=0, column=0)

            row_count = row_count + 1

        c.close
        conn.close()
        search_window.destroy()
        searchresult_window.lift()

    def search_by_keyword():
        searchresult_window = Tk()
        searchresult_window.title('Program - Searchresult')

        #Checks the number of searchresults
        given_keyword = keyword.get()
        conn = sqlite3.connect('database.db')
        c = conn.cursor()
        c.execute("SELECT COUNT() FROM entry_table WHERE subject LIKE '%'||?||'%' OR header LIKE '%'||?||'%' OR entry LIKE '%'||?||'%'",
                  (given_keyword, given_keyword, given_keyword))
        number = int(str(c.fetchone()).replace(",","").replace("(","").replace(")",""));

        #Gets data from database
        c.execute("SELECT * FROM entry_table WHERE subject LIKE '%'||?||'%' OR header LIKE '%'||?||'%' OR entry LIKE '%'||?||'%'",
                  (given_keyword, given_keyword, given_keyword))
        data = c.fetchall()
        row_count = 0

        #Scrollbar
        main_frame = Frame(searchresult_window)
        main_frame.pack(fill=BOTH, expand=1)
        my_canvas = Canvas(main_frame)
        my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
        my_scroblbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
        my_scroblbar.pack(side=RIGHT, fill=Y)
        my_canvas.configure(yscrollcommand=my_scroblbar.set)
        my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
        seccond_frame = Frame(my_canvas)
        my_canvas.create_window((0,0), window=seccond_frame, anchor="nw")

        # Displays searchresults on screen
        for _ in range(number):
            searchresult_frame = LabelFrame(seccond_frame, pady=5, bg='yellow1')
            searchresult_frame.pack()
            data_label = Label(searchresult_frame, text=data[row_count][1], borderwidth=5, relief="groove", width=10)
            data_label.grid(row=0, column=0)

        c.close
        conn.close()
        search_window.destroy()
        searchresult_window.lift()

    #Show all button
    all_btn = Button(search_window, text="Show all entries", pady=5, bg='yellow1', command=search_all)
    all_btn.grid(row=0, column=0)

    #Search by keyword frame (including: entry field and search button)
    search_by_keyword_frame = LabelFrame(search_window, text="Search by keyword", pady=5, bg='yellow1')
    search_by_keyword_frame.grid(row=1, column=0)
    keyword = Entry(search_by_keyword_frame)
    keyword.delete(0, END)
    keyword.insert(END, str("Give Keyword"))
    keyword.grid(row=0, column=0)
    hae = Button(search_by_keyword_frame, text="SEARCH", pady=5, bg='yellow1', command=search_by_keyword)
    hae.grid(row=1, column=0)

    return_btn = Button(search_window, text="Return", pady=5, bg='yellow1', command =search_window.destroy)
  

      return_btn.grid(row=2, column=0, pady=5)
    
    
    search_btn = Button(root, text="Search", pady=5, bg='yellow1', command=search)
    search_btn.grid(row=2, column=0, pady=5)
    
    
    root.mainloop()

I realize parts #Scrollbar and #Displays Search results on screen are the exact same and I want to call a function insted of it.我意识到屏幕上的#Scrollbar 和#Displays 搜索结果部分完全相同,我想调用它的 function。 However it seems that no matter where I define the function (for scrollbar and Display) I always get error.但是,似乎无论我在哪里定义 function(用于滚动条和显示),我总是会出错。 Here is one example that I have tried:这是我尝试过的一个示例:

from tkinter import *
import sqlite3
from tkinter import ttk

root = Tk()
root.title('Program')

def search():
search_window = Toplevel(root)
search_window.title('Program - Search')

def function1():
    # Scrollbar
    main_frame = Frame(searchresult_window)
    main_frame.pack(fill=BOTH, expand=1)
    my_canvas = Canvas(main_frame)
    my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
    my_scroblbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
    my_scroblbar.pack(side=RIGHT, fill=Y)
    my_canvas.configure(yscrollcommand=my_scroblbar.set)
    my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
    seccond_frame = Frame(my_canvas)
    my_canvas.create_window((0, 0), window=seccond_frame, anchor="nw")

    # Displays searchresults on screen
    for _ in range(number):
        searchresult_frame = LabelFrame(seccond_frame, pady=5, bg='yellow1')
        searchresult_frame.pack()
        data_label = Label(hakutulos_frame, text=data[row_count][1], borderwidth=5, relief="groove", width=10)
        data_label.grid(row=0, column=0)

        row_count = row_count + 1

def search_all():
    searchresult_window = Tk()
    searchresult_window.title('Program - Searchresult')

    #Checks the number of searchresults
    conn = sqlite3.connect('database.db')
    c = conn.cursor()
    c.execute('SELECT COUNT() FROM entry_table')
    number = int(str(c.fetchone()).replace(",","").replace("(","").replace(")",""));

    #Gets data from database
    c.execute('SELECT * FROM entry_table')
    data = c.fetchall()
    row_count = 0

    function1()

    c.close
    conn.close()
    search_window.destroy()
    searchresult_window.lift()

def search_by_keyword():
    searchresult_window = Tk()
    searchresult_window.title('Program - Searchresult')

    #Checks the number of searchresults
    given_keyword = keyword.get()
    conn = sqlite3.connect('database.db')
    c = conn.cursor()
    c.execute("SELECT COUNT() FROM entry_table WHERE subject LIKE '%'||?||'%' OR header LIKE '%'||?||'%' OR entry LIKE '%'||?||'%'",
              (given_keyword, given_keyword, given_keyword))
    number = int(str(c.fetchone()).replace(",","").replace("(","").replace(")",""));

    #Gets data from database
    c.execute("SELECT * FROM entry_table WHERE subject LIKE '%'||?||'%' OR header LIKE '%'||?||'%' OR entry LIKE '%'||?||'%'",
              (given_keyword, given_keyword, given_keyword))
    data = c.fetchall()
    row_count = 0

    function1()

    c.close
    conn.close()
    search_window.destroy()
    searchresult_window.lift()

#Show all button
all_btn = Button(search_window, text="Show all entries", pady=5, bg='yellow1', command=search_all)
all_btn.grid(row=0, column=0)

#Search by keyword frame (including: entry field and search button)
search_by_keyword_frame = LabelFrame(search_window, text="Search by keyword", pady=5, bg='yellow1')
search_by_keyword_frame.grid(row=1, column=0)
keyword = Entry(search_by_keyword_frame)
keyword.delete(0, END)
keyword.i

nsert(END, str("Give Keyword"))
    keyword.grid(row=0, column=0)
    hae = Button(search_by_keyword_frame, text="SEARCH", pady=5, bg='yellow1', command=search_by_keyword)
    hae.grid(row=1, column=0)

    return_btn = Button(search_window, text="Return", pady=5, bg='yellow1', command =search_window.destroy)
    return_btn.grid(row=2, column=0, pady=5)


search_btn = Button(root, text="Search", pady=5, bg='yellow1', command=search)
search_btn.grid(row=2, column=0, pady=5)


root.mainloop()

This is your error output:这是您的错误 output:

Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\Name\AppData\Local\Programs\Python\Python38-32\lib\tkinter_init_.py", line 1883, in call return self.func(*args) File "C:/Users/Name/PycharmProjects/test/venv/Testi.py", line 49, in search_all function1() File "C:/Users/Name/PycharmProjects/test/Testi.py", line 14, in function1 main_frame = Frame(searchresult_window) NameError: name 'searchresult_window' is not defined

The root error the interpreter complain about is this bit:解释器抱怨的根本错误是这一点:

line 14, in function1 main_frame = Frame(searchresult_window) NameError: name 'searchresult_window' is not defined

Meaning, Python interpreter can't find the variable searchresult_window to use it inside function1 because that is not in function1's scope.意思是,Python 解释器找不到变量searchresult_window在函数 1 中使用它,因为它不在函数 1 的 scope 中。 You have defined the variable inside some other function ( search_all ) and not passing it to function1.您已经在其他一些 function ( search_all ) 中定义了变量,并且没有将其传递给 function1。 You should either pass the variable to function1 or define the variable in a scope where function1 has access to it.您应该将变量传递给 function1 或在 scope 中定义变量,其中 function1 可以访问它。 I defined the variable in the global scope, this should resolve the issue.我在全局 scope 中定义了变量,这应该可以解决问题。

searchresult_window = Tk()
searchresult_window.title('Program - Searchresult')

def function1():
    # Scrollbar
    main_frame = Frame(searchresult_window)
    main_frame.pack(fill=BOTH, expand=1)
    my_canvas = Canvas(main_frame)
    my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
    my_scroblbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
    my_scroblbar.pack(side=RIGHT, fill=Y)
    my_canvas.configure(yscrollcommand=my_scroblbar.set)
    my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
    seccond_frame = Frame(my_canvas)
    my_canvas.create_window((0, 0), window=seccond_frame, anchor="nw")

    # Displays searchresults on screen
    for _ in range(number):
        searchresult_frame = LabelFrame(seccond_frame, pady=5, bg='yellow1')
        searchresult_frame.pack()
        data_label = Label(hakutulos_frame, text=data[row_count][1], borderwidth=5, relief="groove", width=10)
        data_label.grid(row=0, column=0)

        row_count = row_count + 1

def search_all():    
    #Checks the number of searchresults
    conn = sqlite3.connect('database.db')
    c = conn.cursor()
    c.execute('SELECT COUNT() FROM entry_table')
    number = int(str(c.fetchone()).replace(",","").replace("(","").replace(")",""));

    #Gets data from database
    c.execute('SELECT * FROM entry_table')
    data = c.fetchall()
    row_count = 0

    function1()

    c.close
    conn.close()
    search_window.destroy()
    searchresult_window.lift()

Let's use your example / question and explain two options regarding Python.让我们使用您的示例/问题并解释有关 Python 的两个选项。

The issue is that you create search_window inside the method search() so it is defined only there.问题是您在方法 search() 中创建了 search_window ,因此它仅在此处定义。

Python as a programming language gives you many alternatives (like any other programming language) Python 作为一种编程语言为您提供了许多选择(就像任何其他编程语言一样)

Option 1: use return选项 1:使用返回

You can return the variable from the method and then use it in other location您可以从方法中返回变量,然后在其他位置使用它

def search():
    search_window = Toplevel(root)
    search_window.title('Program - Search')
    return search_window  # i added this line at the end of the function

later in the code you can do this:稍后在代码中你可以这样做:

    search_window = search()

Option 2: global keyword选项 2:全局关键字

Python gives you an ability to update (or define) global variables from inside a method. Python 使您能够从方法内部更新(或定义)全局变量。

def search():
    global search_window # added ths line to define global variable
    search_window = Toplevel(root)
    search_window.title('Program - Search')

Do not forget to call search() somewhere below (you don't do that in your example).不要忘记在下面的某个地方调用search() (在您的示例中您没有这样做)。 From that point on, you will have a new variable named search_window.从那时起,您将拥有一个名为 search_window 的新变量。 Simply approach it.简单地接近它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM