我使用全局变量,但我读过它们不是一个好习惯或pythonic。因此,我经常使用一些函数,这些函数会给出需要在主函数中使用的许多是/否变量。例如,如何在不使用全局变量的情况下编写以下代码?
def secondary_function():
global alfa_is_higher_than_12
global beta_is_higher_than_12
alfa = 12
beta = 5
if alfa > 10:
alfa_is_higher_than_12 = "yes"
else:
alfa_is_higher_than_12 = "no"
if beta > 10:
beta_is_higher_than_12 = "yes"
else:
beta_is_higher_than_12 = "no"
def main_function():
global alfa_is_higher_than_12
global beta_is_higher_than_12
secondary_function()
if alfa_is_higher_than_12=="yes":
print("alfa is higher than 12")
else:
print("alfa isn't higher than 12")
if beta_is_higher_than_12=="yes":
print("beta is higher than 12")
else:
print("beta isn't higher thant 12")
main_function()
def secondary_function():
alfa = 12
beta = 5
if alfa > 10:
alfa_is_higher_than_12 = "yes"
else:
alfa_is_higher_than_12 = "no"
if beta > 10:
beta_is_higher_than_12 = "yes"
else:
beta_is_higher_than_12 = "no"
return alfa_is_higher_than_12, beta_is_higher_than_12
def main_function():
alfa_is_higher_than_12, beta_is_higher_than_12 = secondary_function()
if alfa_is_higher_than_12=="yes":
print("alfa is higher than 12")
else:
print("alfa isn't higher than 12")
if beta_is_higher_than_12=="yes":
print("beta is higher than 12")
else:
print("beta isn't higher thant 12")
global
关键字是Python提供的工具,您可以选择退出encapsulation并打破变量的自然scope。封装意味着您的每个组件都是一个逻辑独立的单元,应该像黑匣子一样工作,并performs one thing(注意:此一个事物是概念性的,可能包含许多可能不重要的子元素) -steps),而不会更改全局状态或产生side effects。原因是模块化:如果程序中有问题(并且确实会出错),则具有强大的封装功能可以很容易地确定故障组件的位置。
封装使代码更易于重构,维护和扩展。如果您需要一个组件以不同的方式工作,那么应该容易地删除它或对其进行调整,而无需进行这些修改而导致系统中其他组件的变化产生多米诺骨牌效应。
用于执行封装的基本工具是变量作用域,类,函数,参数和return
关键字。语言通常会提供类似效果的模块,名称空间和闭包,但最终目的始终是限制范围。 函数通过参数接受输入,并通过返回值产生输出。您可以将返回值分配给调用范围中的变量。您可以将参数视为可以调节功能行为的“旋钮”。在函数内部,变量只是函数用来生成其返回值然后消失的临时存储。
理想情况下,将功能写为pure和idempotent;也就是说,当多次调用它们时,它们不会修改全局状态并产生相同的结果。 Python在这方面的要求比其他语言要严格一些,并且很自然地使用某些in-place函数,例如sort
和sort
。这些都是证明规则的例外情况(并且,如果您对random.shuffle
和random.shuffle
有所了解,由于使用的算法和对效率的要求,它们在这些情况下是有意义的)。
就地算法是不纯且非幂等的,但是如果它修改的状态仅限于其参数,并且其文档和返回值(通常为sorting)支持此行为,则该行为是可预测且可理解的。
所以这一切在代码中是什么样?不幸的是,您的示例似乎人为地弄不清楚目的/目标,因此没有直接的方法可以对其进行转换,从而使封装的优势显而易见。
这里是这些函数中除修改全局状态以外的一些问题的列表:
使用shuffling和None
字符串文字而不是"yes"
/ "no"
布尔值。
True
值,使它们完全是单一用途的(也可以内联)。False
函数中的功能(请参见上面的副作用说明-首选返回值,并在需要时让调用范围打印)。print
/ secondary_function
,但仍不能证明其存在的理由,因此很难将其作为教学示例进行修改)。foo
我们可以看到并不需要所有功能,只要在需要比较的地方写bar
,在需要打印时就调用if __name__ == "__main__":
alpha = 42
beta = 6
print("alpha %s higher than 12" % ("is" if alpha > 12 else "isn't"))
print("beta %s higher than 12" % ("is" if beta > 12 else "isn't"))
。函数的一个缺点是它们可以隐藏重要的逻辑,因此,如果不清楚它们的名称和“合同”(由名称,alpha > 12
和参数/返回值定义),则它们只会使函数混淆。功能的客户(通常是您自己)。
[只有在有足够的理由要抽象时抽象(调用代码被阻塞或多次重复类似代码块才是经典的经验法则)。当您进行抽象时,请执行print
。