中断20年后重新开始编程。一直在阅读的内容是,在python中使用全局变量是不良设计的标志,但无法找到一种更好的方法。
下面是一个小程序,它利用全局变量“ paused”来确定音乐播放器的状态。此变量由几个函数使用。
在不利用全局变量的情况下还有更好的方法吗?
# Global variable to access from multiple functions
paused = False
def play_music():
global paused
if not paused:
try:
mixer.music.load(filename)
mixer.music.play()
statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
except:
tkinter.messagebox.showerror('File not found',
'Melody could not find the file.')
else:
mixer.music.unpause()
paused = False
statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
def stop_music():
mixer.music.stop()
statusBar['text'] = 'Music stopped'
def pause_music():
global paused
if not paused:
mixer.music.pause()
paused = True
statusBar['text'] = 'Music paused'
else:
play_music()
答案 0 :(得分:8)
您可以将所有函数放在一个类中,并将“全局”变量设置为属性。这样,您可以在方法之间共享它:
class Player(object):
def __init__(self):
self.paused = False
def play_music(self):
if not self.paused:
# and so on
def pause_music(self):
if not self.paused:
# etc.
答案 1 :(得分:1)
万一其他人感兴趣,下面是经过改进的代码,其中创建了一个Player类来封装暂停变量:
import os
from tkinter import *
from tkinter import filedialog
import tkinter.messagebox
from pygame import mixer
# Global variable to access from multiple functions
# paused = False
class Player:
def __init__(self):
self.paused = False
self.filename = None
def play_music(self):
if not self.paused:
try:
mixer.music.load(self.filename)
mixer.music.play()
statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
except FileNotFoundError:
tkinter.messagebox.showerror('File not found',
'Melody could not find the file. Please choose a music file to play')
else:
mixer.music.unpause()
self.paused = False
statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
@staticmethod
def stop_music():
mixer.music.stop()
statusBar['text'] = 'Music stopped'
def pause_music(self):
if not self.paused:
mixer.music.pause()
self.paused = True
statusBar['text'] = 'Music paused'
else:
self.play_music()
def rewind_music(self):
self.play_music()
statusBar['text'] = 'Music rewound'
@staticmethod
def set_volume(val):
# val is set automatically by the any tkinter widget
volume = int(val)/100 # mixer only takes value between 0 and 1
mixer.music.set_volume(volume)
# Create about us Message Box
@staticmethod
def about_us():
tkinter.messagebox.showinfo('About Melody', 'This is a music player built using python and tkinter')
def browse_file(self):
self.filename = filedialog.askopenfilename()
print(self.filename)
# Create main window
root = Tk()
# Create window frames
middle_frame = Frame(root)
bottom_frame = Frame(root)
# Create Menu
menu_bar = Menu(root)
root.config(menu=menu_bar)
# Create Player object
player = Player()
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Open", command=player.browse_file)
subMenu.add_command(label="Exit", command=root.destroy)
# it appears we can re-use subMenu variable and re-assign it
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Help", menu=subMenu)
subMenu.add_command(label="About Us", command=player.about_us)
# Initialise Mixer
mixer.init()
# Create and set the main window
root.title("Melody")
root.wm_iconbitmap(r'favicon.ico')
# root.geometry('300x300')
# Create and arrange widgets
text = Label(root, text="Lets make some noise!")
text.pack(pady=10)
middle_frame.pack(pady=30, padx=30) # Place the middle and bottom frame below this text
bottom_frame.pack()
playPhoto = PhotoImage(file='play-button.png')
playBtn = Button(middle_frame, image=playPhoto, command=player.play_music)
playBtn.grid(row=0, column=0, padx=10)
stopPhoto = PhotoImage(file='stop-button.png')
stopBtn = Button(middle_frame, image=stopPhoto, command=player.stop_music)
stopBtn.grid(row=0, column=1, padx=10)
pausePhoto = PhotoImage(file='pause-button.png')
pauseBtn = Button(middle_frame, image=pausePhoto, command=player.pause_music)
pauseBtn.grid(row=0, column=2, padx=10)
rewindPhoto = PhotoImage(file='rewind-button.png')
rewindBtn = Button(bottom_frame, image=rewindPhoto, command=player.rewind_music)
rewindBtn.grid(row=0, column=0, padx=20)
# Create and set volume slider
scale = Scale(bottom_frame, from_=0, to=100, orient=HORIZONTAL, command=player.set_volume)
scale.set(70) # set default slider and and volume
player.set_volume(70)
scale.grid(row=0, column=1, padx=10)
statusBar = Label(root, text='Welcome to Melody', relief=SUNKEN, anchor=W)
statusBar.pack(side=BOTTOM, fill=X)
# Keep main window displayed
root.mainloop()
答案 2 :(得分:0)
实际上,不建议使用全局变量。您可能会有副作用,导致程序出现意外行为。
上面有可能(使用类),但是另一种解决方案是将变量作为函数的参数传递。
def play_music(paused):
...
def stop_music(paused):
...
def pause_music(paused):
...
答案 3 :(得分:0)
如果您不想使用类,则可以传递一个带有暂停键的设置字典,该字典将在您的所有函数中发生变化
def play_music(settings):
# some extra code
settings['pause'] = False
def stop_music(settings)
# some extra code
settings['pause'] = None
def pause_music(settings):
# some extra code
settings['pause'] = True
def main():
settings = {'pause': None}
play_music(settings)
.....