问题 链接
self关键字的作用是什么? 我理解他用户在创建class时具体化实例,但我无法理解为何需要给每个方法加入self作为参数.
举例,在ruby中,我这么做:
class myClass
def myFunc(name)
@name = name
end
end
我可以很好地理解,非常简单.但是在Python中,我需要去加入self:
class myClass:
def myFunc(self, name):
self.name = name
有谁能解释下么?
使用self关键字的原因是,Python没有@语法用于引用实例属性.Python决定用一种方式声明方法:实例对象自动传递给属于它的方法,但不是接收自动化:方法的第一个参数是调用这个方法的实例对象本身.这使得方法整个同函数一致,并且由你自己决定真实的名(虽然self是约定,但当你使用其他名的时候,通常人们并不乐意接受).self对于代码不是特殊的,只是另一个对象.
Python本来可以做一些用来区分真实的名字和属性的区别 —— 像Ruby有的特殊语法,或者像C++/Java的命令声明,或者其他可能的的语法 —— 但是Python没有这么做.Python致力于使事情变得明确简单,让事情是其本身,虽然并不是全部地方都这么做,但是实例属性石这么做的!这就是为什么给一个实例属性赋值时需要知道是给哪个实例赋值,并且,这就是为什么需要self
举例
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
等价于
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
另外
v_instance.length()
转为
Vector.length(v_instance)
问题 链接
Python允许我们创建'private' 函数:变量以两个下划线开头,像这样: __myPrivateMethod(). 但是,如何解释:
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
dir(obj) 和 obj._MyClass__myPrivateMethod()
回答
‘private'只是用作,确保子类不会意外覆写父类的私有方法和属性.不是为了保护外部意外访问而设计的!
例如:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
当然,这对于两个同名的类没有作用
另外,可以查看diveintopython的解释 入口
问题 链接
我现在意识到,我不需要像我在使用java的static方法那样使用类方法,但是我不确定什么时候使用
谁能通过一个好的例子解释下Python中的类方法,至少有人能告诉我什么时候确实需要使用类方法
类方法用在:当你需要使用不属于任何明确实例的方法,但同时必须涉及类.有趣的是,你可以在子类中覆写,这在Java的static方法和Python的模块级别函数中是不可能做到的
如果你有一个MyClass, 并且一个模块级别函数操作MyClass(工厂,依赖注入桩等等), 声明一个类方法.然后这个类方法可以在子类中调用
问题 链接
我很疑惑,为何__init__总是在__new__之后调用
如下
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
输出
NEW
INIT
EXISTS
INIT
EXISTS
INIT
有木有人可以解释一下
来自 链接
使用__new__,当你需要控制一个实例的生成
使用__init__,当你需要控制一个实例的初始化
__new__是实例创建的第一步.最先被调用,并且负责返回类的一个新实例.
相反的,__init__不返回任何东西,只是负责在实例创建后进行初始化
通常情况下,你不必重写__new__除非你写一个子类继承不可变类型,例如str,int,unicode或tuple
你必须了解到,你尝试去做的用Factory可以很好地解决,并且是最好的解决方式.使用__new__不是一个简洁的处理方式,一个factory例子
问题 链接
x.__class__.__name__
问题 链接
staticmethod,静态方法在调用时,对类及实例一无所知
仅仅是获取传递过来的参数,没有隐含的第一个参数,在Python里基本上用处不大,你完全可以用一个模块函数替换它
classmethod, 在调用时,将会获取到其所在的类,或者类实例,作为其第一个参数
当你想将函数作为一个类工厂时,这非常有用: 第一个参数是类,你可以实例化出对应实例对象,甚至子类对象。
可以观察下 dict.fromkey(),是一个类方法,当子类调用时,返回子类的实例
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
问题 链接
使用 staticmethod装饰器
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
问题 链接
在类中定义的变量,不在方法定义中,成为类变量或静态变量
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
i是类级别的变量,但这里要和实例级别的变量i区分开
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
这和C++/java完全不同,但和C#区别不大,C#不允许类实例获取静态变量
具体见 what the Python tutorial has to say on the subject of classes and class objects
另外,静态方法
class C:
@staticmethod
def f(arg1, arg2, ...): ...
问题 链接
if hasattr(a, 'property'):
a.property
两种风格
EAFP(easier to ask for forgiveness than permission)
LBYL(look before you leap)
相关内容 EAFP vs LBYL (was Re: A little disappointed so far) EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python
try:
doStuff(a.property)
except AttributeError:
otherStuff()
or
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
问题 链接
我不认为有必要,一个拥有函数的模块(不是类)可以作为很好的单例使用,它的所有变量被绑定到这个模块,无论如何都不能被重复实例化
如果你确实想用一个类来实现,在python中不能创建私有类或私有构造函数,所以你不能隔离多个实例而仅仅通过自己的API来访问属性
我还是认为将函数放入模块,并将其作为一个单例来使用是最好的办法