我曾经是一名c程序员,因此我们必须将每个变量作为参数或指针传递,而不是鼓励他们定义全局变量。
我将在python中的几个函数中使用一些变量。
通常,哪个更好,将变量作为参数传递,或者在获取变量值时定义自变量? python是否有关于此的一般规则?
像这样:
class A:
def func2(self, var):
print var
def func1(self):
var = 1
self.func2(var)
class B:
def func2(self):
print self.var
def func1(self):
self.var = 1
self.func2()
哪个更好? A或B?
答案 0 :(得分:3)
在Python中,你有很多自由去做“有意义”的事情。在这种情况下,我会说这取决于您计划如何使用func2
以及谁将访问它。如果func2
只应该对self.var
采取行动,那么您应该对其进行编码。如果其他对象需要将不同的参数传递给func2
,那么您应该允许它作为参数。当然,这一切都取决于你想要做的的更大范围,但是根据你的简单例子,这是有道理的。
另外,我对你的问题与全局变量的关系感到困惑。成员变量与全局变量不同。
编辑以反映更新的帖子:
您的示例中A和B之间的区别在于B会保留有关self.var
的信息,而A则不会。如果var
需要作为对象状态的一部分保留,则需要将其存储为self
的一部分。我感觉你的问题可能更多地与对象相关,而不是任何特定于Python的概念。
答案 1 :(得分:1)
当然,设计程序以智能地使用范围会更好。最明显的问题是全局变量的变异会以难以跟踪的方式影响远程代码部分,但此外,当您的引用存在于长寿范围内时,垃圾收集(引用计数,无论如何)变得没有实际意义
也就是说,Python有一个global
关键字,但它没有像c
那样拥有全局变量。 Python全局变量是模块级别,因此默认情况下它们与模块一起命名。下游程序员可以绕过或别名这个命名空间,但这是他/她的问题。当然,定义模块级配置值,伪枚举或-const是有意义的。
接下来,考虑是否需要维护状态:如果对象的行为取决于它是否知道某个值,则将其设为属性。您可以通过将值附加到self
来实现。否则,只需将值作为参数传递。 (但是,如果你有很多方法和没有状态,问问自己是否真的需要一个类,或者它们应该只是模块函数?)
答案 2 :(得分:1)
这些问题对面向对象的设计有影响。 Python是一种面向对象的语言; c不是。你会极大地破坏(在某些情况下会阻碍)面向对象的优势,以便在Python中使用进出编程或全局变量,除非有特殊原因这样做。
考虑以下原因,但并非详尽无遗:
您可能会遇到基元问题,因为与C不同,Python不允许您(轻松地)跟踪对象的引用。如果我传入一个整数变量,我不能仅在函数范围内更改其原始位置的变量值。这可以通过全局变量来解决,但只能是非常混乱。请考虑以下代码:
def foo(x):
x = 3
myVar = 5
foo(myVar)
print(myVar)
当然,这将输出5而不是3。 C中没有“x*
”,所以如果我们想要foo将3重新分配给输入变量,那么在Python中解决这个问题会相当棘手。相反,我们可以写
class Foo:
x = 5
def foo( fooObj ):
fooObj.x = 3
myFoo = Foo()
foo(myFoo)
print(myFoo.x)
问题解决了 - 它现在输出3,而不是5!
答案 3 :(得分:0)
作为一般规则,最好尽可能使用self
来封装内部信息并将其绑定到对象(或类)。我可能会帮助解释self
和类如何工作。
在Python类中,对象变量显式传递给方法,就像你想要做OOP一样。这与其他面向对象的语言不同,例如Java或C ++,其中该参数是隐式传递的(但它始终是!)。 因此,如果您定义类如:
Class B(object):
def __init__(self, var=None): # this is constructor
self.var = var
def func2(self):
print self.var
当您使用.
运算符调用object方法时,此对象将作为第一个参数传递,该方法映射到方法签名中的self
:
b = B(1) # object b is created and B.__init__(b, 1) is called
b.func2() # B.func2(b) is called, outputs 1
我希望这能为你解决一些事情
答案 4 :(得分:0)
我建议关注接近度。如果变量仅与当前方法相关或者被创建为传递给另一个方法,那么它可能不表示类实例的持久状态。完成后创建变量并将其丢弃。
如果变量描述了实例的重要方面,请使用self
。这并不是因为变量被封装在实例中而侵犯了对全局变量的厌恶。出于同样的原因,类和模块变量也很好。
简而言之,A和B都是正确的实现,具体取决于上下文。对不起,我没有给你一个明确的答案,但它更多地与对象对周围物体的重要程度有关,而不是维持任何类型的社区标准。你问这个问题让我觉得你会做出合理的判断。