我使用wxPython在Python中编写了一个Cryptoquote Generator。我对wxPython本身并没有任何问题,而是重置我的变量。我的程序以这种方式工作:我有一个生成加密报价的按钮。然后,用户按下一个解码按钮,一次更改一个字母。有一个按钮可以重置整个报价,还有一个按钮可以一步一步地重置更改。
我有一个base_copy
变量来存储原始加密报价。它是一个空列表,在调用on_generate_quote
时一次填充加密引号的各个字符。它在整个循环中保持不变 - 因此我可以使用on_clear_all
或on_clear_last
调用它来重置我的加密引用。问题是,如果我使用我的decode_button
来解码一封信,那么请再次使用我的clear_all_button
,再使用decode_button
,clear_all_button
调用base_copy
现在已经以某种方式被改变的字母污染了,这些字母应该只在我的split_cryptoquote
副本中。为什么会这样,因为我从未暗中调用改变base_copy
? (但是,我会在on_clear_all
拨打电话,将split_cryptoquote
设置为base_copy
,但这不应该更改base_copy
。)
#/------------------ wxPython GUI -----------------\
class MainWindow(wx.Frame):
quote = []
quote.append(quote_fetch(quotes))
split_cryptoquote = []
base_copy = []
split_buffer = []
buffer_origin = None
buffer_replace = None
quote_altered = False #Becomes true after first decoding change.
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title="Cryptogrammar", size=(1000, 200))
self.CreateStatusBar()
self.txt = wx.StaticText(self, -1, "".join(MainWindow.split_cryptoquote), (20,30), (40,40))
self.txt.SetForegroundColour("WHITE")
#Menu
filemenu = wx.Menu()
menu_about = filemenu.Append(wx.ID_ABOUT, "&About", " Information about this program")
menu_how = filemenu.Append(HOW_TO, "&How to Play", " How to play Cryptogrammar")
menu_exit = filemenu.Append(wx.ID_EXIT,"E&xit", " Close Cryptogrammar")
#menuGenerate = filemenu.Append(wx.ID_NONE, "&Generate New", "Generate a new cryptogram")
#menu_bar
menu_bar = wx.MenuBar()
menu_bar.Append(filemenu, "&File")
self.SetMenuBar(menu_bar)
#Buttons
generate_button = wx.Button(self, -1, "&Generate Cryptogram")
decode_button = wx.Button(self, -1, "&Decode Letter")
clear_all_button = wx.Button(self, -1, "&Clear All Changes")
clear_last_button = wx.Button(self, -1, "Clear &Last Change")
answer_button = wx.Button(self, -1, "Show &Answer")
but_list = [generate_button, decode_button, clear_all_button, clear_last_button, answer_button]
#Sizers
self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
for i in range(0, 5):
self.sizer2.Add(but_list[i], 1, wx.EXPAND)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.txt, 1, wx.EXPAND)
self.sizer.Add(self.sizer2, 0, wx.EXPAND)
#Events
self.Bind(wx.EVT_MENU, self.on_about, menu_about)
self.Bind(wx.EVT_MENU, self.on_exit, menu_exit)
self.Bind(wx.EVT_MENU, self.on_how, menu_how)
self.Bind(wx.EVT_BUTTON, self.on_generate_quote, generate_button)
self.Bind(wx.EVT_BUTTON, self.on_decode, decode_button)
self.Bind(wx.EVT_BUTTON, self.on_answer, answer_button)
self.Bind(wx.EVT_BUTTON, self.on_clear_all, clear_all_button)
self.Bind(wx.EVT_BUTTON, self.on_clear_last, clear_last_button)
self.SetSizer(self.sizer)
self.SetAutoLayout(1)
self.sizer.Fit(self)
self.SetTitle("Cryptogrammar")
self.Centre()
def on_about(self, e):
dialogue = wx.MessageDialog(self, "A program for generating random cryptograms.\n\n\n\nCopyright 2014 Joshua Simmons\nVersion 0.1.0", "About Cryptogrammar", wx.OK)
dialogue.ShowModal()
dialogue.Destroy()
def on_exit(self, e):
self.Close(True)
def on_how(self, e):
dialogue = wx.MessageDialog(self, "HOW TO PLAY:\n\n\n--\tPress the 'Generate Cryptogram' to spawn a cryptogram.\n\n--\tUse the 'Decode Letter' to replace an encrypted letter with a letter of your choice. 'Decoded' letters will be lowercase to distinguish them.\n\n--\tUse the 'Clear Changes' button to reset the puzzle.\n\n--\t'Show Answer' solves the puzzle!", "How to play Cryptogrammar", wx.OK)
dialogue.ShowModal()
dialogue.Destroy()
def on_decode(self, e):
dialogue = wx.TextEntryDialog(self, "Which letter do you wish to change? Use format: 'a=e'", "Decode Letter", "")
dialogue.ShowModal()
decode = dialogue.GetValue()
#Text entry filter
match = re.search(r'\w+=\w+|^\d*$', decode)
if not match:
err = wx.MessageDialog(self, "That is not a correct entry format.", "Entry Error", style=wx.ICON_HAND)
err.ShowModal()
#Letter replacement
else:
if not MainWindow.quote_altered:
MainWindow.buffer_origin = decode[0].upper()
MainWindow.buffer_replace = decode[2].upper()
else:
for n in range(0, len(MainWindow.split_buffer)):
if MainWindow.split_buffer[n] == MainWindow.buffer_origin:
MainWindow.split_buffer[n] = MainWindow.buffer_replace.lower()
MainWindow.buffer_origin = decode[0].upper()
MainWindow.buffer_replace = decode[2].upper()
origin = decode[0].upper()
replace = decode[2].upper() #For resetting changes one at a time.
for n in range(0, len(MainWindow.split_cryptoquote)):
if MainWindow.split_cryptoquote[n] == origin:
MainWindow.split_cryptoquote[n] = replace.lower()
MainWindow.quote_altered = True
origin = None
replace = None
self.txt.SetLabel("".join(MainWindow.split_cryptoquote))
self.sizer.Layout()
dialogue.Destroy()
def on_generate_quote(self, e):
MainWindow.quote.pop()
MainWindow.quote.append(quote_fetch(quotes))
cryptoquote = generate_cryptogram(MainWindow.quote[0], encrypt_key(shuffle_alphabet()))
MainWindow.split_cryptoquote = []
MainWindow.base_copy = []
for i in cryptoquote:
MainWindow.split_cryptoquote.append(i)
MainWindow.base_copy.append(i)
MainWindow.split_buffer.append(i)
self.txt.SetLabel("".join(MainWindow.split_cryptoquote))
self.txt.SetForegroundColour("BLACK")
self.sizer.Layout()
def on_answer(self, e):
if len(MainWindow.base_copy) == 0:
err = wx.MessageDialog(self, "You haven't generated a puzzle yet, doofus!", "Encryption Error", style=wx.ICON_HAND)
err.ShowModal()
else:
self.txt.SetLabel(MainWindow.quote[0])
self.txt.SetForegroundColour("BLUE")
self.sizer.Layout()
def on_clear_last(self, e):
if MainWindow.quote_altered:
self.txt.SetLabel("".join(MainWindow.split_buffer))
else:
self.txt.SetLabel("".join(MainWindow.base_copy))
self.txt.SetForegroundColour("BLACK")
self.sizer.Layout()
def on_clear_all(self, e):
print MainWindow.base_copy
MainWindow.split_cryptoquote = MainWindow.base_copy
MainWindow.split_buffer = MainWindow.base_copy
MainWindow.quote_altered = False
self.txt.SetLabel("".join(MainWindow.base_copy))
self.txt.SetForegroundColour("BLACK")
self.sizer.Layout()
app = wx.App(False)
frame = MainWindow(None, "Cryptogrammar")
frame.Show()
app.MainLoop()
答案 0 :(得分:1)
(但是,我会在on_clear_all中调用以设置split_cryptoquote 到base_copy,但这不应该改变base_copy。)
你发现了自己的问题:
MainWindow.split_cryptoquote = MainWindow.base_copy
将MainWindow.split_cryptoquote
绑定到与MainWindow.base_copy
相同的对象,因此当您修改其中一个时,您将修改另一个。
如果您将行更改为
MainWindow.split_cryptoquote = MainWindow.base_copy[:]
你将强制python创建一个新对象(MainWindow.base_copy
的副本),不应该出现这个问题。
编辑:以下一行:
我认为MainWindow.split_buffer = MainWindow.base_copy
也需要同样的待遇。
见这个例子:
>>> lista = [1,2]
>>> listb = lista
>>> listb.append(3)
>>> lista
[1, 2, 3]
>>> listb
[1, 2, 3]
>>> listc = lista[:]
>>> listc.append(4)
>>> listc
[1, 2, 3, 4]
>>> lista
[1, 2, 3]