Виноват в том, что вы не должны совместно использовать переменные-члены класса.
Если разные классы совместно используют некоторые общие данные, эти данные, вероятно, являются другим классом, и они могут наследовать его.
class CommonData():
client = 100
class A(CommonData):
def __init__(self):
print(A.client)
class B(CommonData):
def __init__(self):
print(B.client)
a = A()
b = B()
CommonData.client = 300
print(a.client)
print(b.client)
В приведенном выше случае каждый экземпляр A и каждый экземпляр B совместно используют все переменные класса CommonData, например client.
CommonData.client = 400
class C():
pass
Вы также можете использовать множественное наследование.определите все общие данные как атрибуты CommonData и используйте CommonData как класс для хранения данных, как в примере выше, не создавайте экземпляры из него:
class D(C, CommonData):
def __init__(self):
print(D.client)
c = C()
d = D()
Более простой вариант - просто определить переменную CommonDataво внешней области и используйте его из любого места:
common_data = 500
class A():
def __init__(self):
global common_data
print(common_data)
common_data = 200
# ...
Но глобальные переменные, как правило, считаются плохой вещью в программе, поскольку их использование может стать проблемой по нескольким причинам.
ПокаДругой способ - передать переменную инициализатору объекта.Это заставляет экземпляр сохранять свое собственное значение, скопированное из значения создания:
common_data = 600
class A():
def __init__(self, data):
self.common = data
print(self.common)
a = A(common_data)
common_data = 0
print(a.common)
Если вы запустите весь приведенный выше код, он напечатает
100
100
300
300
400
600
600
Редактировать:
Смотрите мой комментарий к вашему ответу и простой пример здесь.Здесь я выбираю две глобальные ссылки на tkinter StringVars.Строковые переменные сами существуют в пространстве имен Tk (), как виджеты;кроме того, они являются глобальными именами Python.
import tkinter as tk
from tkinter import ttk
class Page1(tk.Toplevel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.title('Page1')
self.label1 = ttk.Label(self, text='Filename:')
self.entry1 = ttk.Entry(self, textvariable=input_file1)
self.label1.pack(side=tk.LEFT)
self.entry1.pack()
class Page2(tk.Toplevel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.title('Page2')
self.label1 = ttk.Label(self, text='Filename:')
self.entry1 = ttk.Entry(self, textvariable=input_file2)
self.button1 = ttk.Button(self, text='Copy Here', command=copy_filename)
self.label1.pack(side=tk.LEFT)
self.entry1.pack(side=tk.LEFT)
self.button1.pack()
def copy_filename():
input_file2.set(input_file1.get())
root = tk.Tk() # has to exist for the StringVars to be created
root.iconify()
input_file1 = tk.StringVar()
input_file2 = tk.StringVar()
page1 = Page1(root)
page2 = Page2(root)
root.mainloop()
Теперь в следующем примере показано, как я превращаю строковые переменные в переменные экземпляров Page1 и Page2 (не классов), делая их локальными, а не глобальными.Затем я вынужден передать ссылку на объект виджета page1 в объект виджета page2.
Это выглядит ближе к тому, что вы спрашиваете.
О проблеме MRO, если вы избежите множественного наследования, этого не произойдет.
Или вы обычно справляетесь с этимиспользование super()
В вашем случае ошибка заключается в том, что вы сохраняете виджет в объекте / экземпляре (в self.somename
), а затем пытаетесь вызвать метод виджета, соответствующий названию класса.В классе нет виджета, чтобы вы могли использовать метод.
Таким образом, поиск с использованием порядка разрешения методов не выполняется, поскольку там нет соответствующего имени.
Обратите внимание, что я не использовал множественное наследование, поэтому я мог бы просто написать tk.Frame.
вместо вызова super
.Мне нравится super, потому что в тексте ясно, что я вызываю родительский класс, но super действительно нужен только тогда, когда есть несколько родителей и различные уровни подклассов (обычно образующие ромбовидную форму).
Теперь пример:
import tkinter as tk
from tkinter import ttk
class Page1(tk.Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.input_file1 = tk.StringVar()
self.label1 = ttk.Label(self, text='Filename:')
self.entry1 = ttk.Entry(self, textvariable=self.input_file1)
self.label1.pack(side=tk.LEFT)
self.entry1.pack()
class Page2(tk.Frame):
# note the page1 reference being
# passed to initializer and stored in a var
# local to this instance:
def __init__(self, parent, page1, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.page1 = page1
self.input_file2 = tk.StringVar()
self.label1 = ttk.Label(self, text='Filename:')
self.entry1 = ttk.Entry(self, textvariable=self.input_file2)
self.button1 = ttk.Button(self, text='Copy Here',
command=self.copy_filename)
self.label1.pack(side=tk.LEFT)
self.entry1.pack(side=tk.LEFT)
self.button1.pack()
def copy_filename(self):
# see how the page1 refernce is used to acess
# the Page1 instance
self.input_file2.set(page1.input_file1.get())
root = tk.Tk() # has to exist for the StringVars to be created
page1 = Page1(root)
page2 = Page2(root, page1) # pass a reference to page1 instance
page1.pack(side=tk.LEFT)
page2.pack(side=tk.LEFT)
root.mainloop()