我来自Java世界,正在阅读Bruce Eckels的《Python 3 Patterns, Recipes and idiom》。
在阅读有关类的内容时,会继续说在Python中不需要声明实例变量。你只需要在构造函数中使用它们,它们就在那里了。
例如:
class Simple:
def __init__(self, s):
print("inside the simple constructor")
self.s = s
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':', self.show())
如果这是真的,那么任何Simple类的对象都可以改变类外变量s的值。
例如:
if __name__ == "__main__":
x = Simple("constructor argument")
x.s = "test15" # this changes the value
x.show()
x.showMsg("A message")
在Java中,我们已经学习了公共/私有/受保护变量。这些关键字是有意义的,因为有时您希望类中的变量在类之外没有人可以访问。
为什么Python中不需要这个?
私有变量在Python中或多或少是一种hack:解释器会故意重命名变量。
class A:
def __init__(self):
self.__var = 123
def printVar(self):
print self.__var
现在,如果你试图在类定义之外访问__var,它会失败:
>>> x = A()
>>> x.__var # this will return error: "A has no attribute __var"
>>> x.printVar() # this gives back 123
但你可以很容易地摆脱这种情况:
>>> x.__dict__ # this will show everything that is contained in object x
# which in this case is something like {'_A__var' : 123}
>>> x._A__var = 456 # you now know the masked name of private variables
>>> x.printVar() # this gives back 456
你可能知道OOP中的方法是这样调用的:x. printvar () => A.printVar(x)。如果A.printVar()可以访问x中的某个字段,那么这个字段也可以在A.printVar()之外访问…毕竟,函数是为可重用性而创建的,其中的语句并没有任何特殊的功能。
在Python 3中,如果你只是想“封装”类属性,就像在Java中一样,你可以这样做:
class Simple:
def __init__(self, str):
print("inside the simple constructor")
self.__s = str
def show(self):
print(self.__s)
def showMsg(self, msg):
print(msg + ':', self.show())
要实例化此操作:
ss = Simple("lol")
ss.show()
注意:print(ss.__s)将抛出一个错误。
实际上,Python 3会混淆全局属性名。就像在Java中一样,它将此转换为“私有”属性。属性名仍然是全局的,但是以一种不可访问的方式,就像其他语言中的私有属性一样。
但是不要害怕。没关系。它也起作用了。;)
我是Python的新手但我有c#和JavaScript的背景。就特性而言,Python感觉像是两者的混合体。JavaScript在这方面也有问题,解决方法是创建一个闭包。这可以通过返回不同的对象来防止访问您不想公开的数据。
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
return printer # returns the nested function
# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()
https://www.programiz.com/python-programming/closure
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#emulating_private_methods_with_closures