1
CoX 2012-05-09 11:36:58 +08:00
Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information. >>> class MemberCounter: ... members = 0 ... def init(self): ... MemberCounter.members += 1 ... >>> >>> m1 = MemberCounter() >>> m1.init() >>> >>> print MemberCounter.members 1 >>> >>> m2 = MemberCounter() >>> >>> print MemberCounter.members 1 >>> >>> print m1.members 1 >>> print m2.members 1 不知道lz的输出是怎么回事 |
2
vayn 2012-05-09 11:38:19 +08:00
members 是类属性,而非实例属性
|
3
Cofyc 2012-05-09 11:38:36 +08:00
学 Python 时,记住一句话:"Everything Is an Object"
一切都是对象,你就明白了。 这里,类 MemberCounter 也是对象。 包括类的类型(type)也是对象,type 的 type 是其自身。 |
6
Cofyc 2012-05-09 11:51:19 +08:00
lz 贴的代码有问题,如果按楼主输出,应该少了 m2.init() :
m2 = MemberCounter() m2.init() --- 这段代码里就是在两次 init() 调用中,自增了类对象 MemberCounter 的属性 members。 m1, m2 是 MemberCounter 对象的实例,如果要自增 m1/m2 的 members 属性,需要使用 self.members 访问。 |
7
allenm 2012-05-09 11:51:46 +08:00
@CoX LZ 的代码少了一行 m2.init()
我猜LZ是看的 《Python 基础教程》这本书吧,我看到这个问题,翻了下手边的这本书的相应部分,就看到这些代码了。 LZ尝试把 init 方法的定义改成 self.members += 1 试试看效果。 这个其实也不难理解吧,即使在 JAVA 这种静态语言中,也可以定义一个 static 的属性,可以直接通过 className.proerty 这样访问的。 像 LS 说的,Python 中,要记住“ Everything is an Object " 好吧,我是 python 菜鸟, java 更菜,如果说错了,欢迎指正。 |
9
eerie 2012-05-09 11:54:16 +08:00
cpp也有static member,不知道楼主啥意思
|
10
agui 2012-05-09 11:56:21 +08:00
看的是<python基础教程>吧? 我最近也在看,有问题大家可以一起交流下:)
|
11
levon OP |
12
ipoh 2012-05-09 12:08:11 +08:00
1. 类明明就是抽象的东西,怎么可以MemberCounter.members这样去访问呢
类也是一个对象 2. m2 = MemberCounter()不是新建个instance吗,怎么跟m1也能扯上关系,而且m1.members和m2.members都一样,唉,谁知道类会不会被别人调用,被别人调用会不会导致混乱呢。 python成员变量请用self.members |
13
eerie 2012-05-09 12:20:09 +08:00
@levon 哦,我看楼上几位的回复理解你的意思了
我还以为你知道members是个static variable呢 通过MemberCounter.members调用的是class自身的变量,不是instance的,于是就相当于static的 你没有给instance本身生成members这个变量,你访问的时候应该fallback到class的static变量了?(见我下面的例子) 另外,我仔细看了下你给的那个例子。。。我猜init应该写成__init__,而且并不需要你手动调用吧... >>> class a(): ... n = 0 ... >>> b = a() >>> a.n = 100 >>> a.n 100 >>> b.n 100 |
14
bravluna 2012-05-09 12:20:12 +08:00 1
LZ 可能受了 Java 这类语言的影响,在 py 里类只是个逻辑概念,实质上是个命名空间,模块和函数都是,更实质上都是个字典(可以查看其__dict__属性),类和实例对象稍特殊一些,可以继承(__class__,__base__),所以:
1. 可以这样引用,在 py 里,一切对象都可以用 obj.attr 的形式引用其属性。 2. 赋值操作才会给给对象增加属性,按以上代码 m1 和 m2 字典里根本没有 members 属性,只是继承了 class 的 member 属性。 |
15
chainchan 2012-05-09 13:01:01 +08:00 1
1,MemberCounter.members中的members你直接声明在类的下面,那么你可以把他想成是一个static变量。
2,m1和m2是MemberCounter的实例,而且他们是不同的 >>> id(m1) != id(m2) True 但是m1.members和m2.members是相同的 >>> id(m1.member) == id(m2.member) True 因为他们同时引用的是MemberCounter.members 此外,在Python中,所有的类属性都是公开的,所以需要在设计时需要考虑清楚,以免用户通过不规范的操作来存取封装的数据属性。而且还要告诉你一点,Python提供了动态增加实例属性的特点,比如你可以这样玩。m1.newguy='chainchan' 很方便,但是后果自负。然后你可能会想在C++或者Java里面提供私有性质的访问,Python也提供了__slot__属性。 |
16
sampeng 2012-05-09 13:31:13 +08:00
我觉得应该这么理解python
面向对象,更深的说应该是面向接口。 任何你使用的对象,包括函数都是接口。只要参数传进来他就不管这个货到底是什么。只要有函数自己需要的接口,就会有正确的行为。 这是极灵活的。。。。虽然其他的语言也是这么一说,但是python直接作为强制行为了。为什么python类的属性是没有私有一说的。就是这个原因。只要定义了,那就是一个对外的接口 |
18
hwywhywl 2012-05-09 14:28:14 +08:00
1. MemberCounter 是 type 一个 实例,members 是 MemberCounter 一个属性,生成MemberCounter类的时候,其实是实例化 一个 type。
2. m2是MemberCounter实例,m2 和 MemberCounter 都有一个类似 __dict__ 的属性, m2.members 查找过程: (1) 如果 m2.__dict__ 中有名为 members 的key,则返回 m2.__dict__['members'],如果没有则进入(2)。 (2) 如果 MemberCounter.__dict__ 中有名为 members 的key,则返回 MemberCounter.__dict__['members'],如果没有则进入(3)。 (3) 如果m2没有定义__getatt__(self, name),则抛出attributeerror异常,如果定义有__getatt__(self, name) 则看它如何处理。 |