V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
levon
V2EX  ›  Python

最近闲余在看Python的书,吐槽一下

  •  
  •   levon · 2012-05-09 11:20:43 +08:00 · 4697 次点击
    这是一个创建于 4368 天前的主题,其中的信息可能已经有所发展或是发生改变。
    关于类的,代码:

    class MemberCounter:
    >>>>members = 0
    >>>>def init(self):
    >>>>>>>>MemberCounter.members += 1


    m1 = MemberCounter()
    m1.init()

    print MemberCounter.members

    m2 = MemberCounter()

    print MemberCounter.members

    print m1.members
    print m2.members

    输出
    1
    2
    2
    2

    ===============================
    1. 类明明就是抽象的东西,怎么可以MemberCounter.members这样去访问呢,困惑
    2. m2 = MemberCounter()不是新建个instance吗,怎么跟m1也能扯上关系,而且m1.members和m2.members都一样,唉,谁知道类会不会被别人调用,被别人调用会不会导致混乱呢。

    实战过的朋友帮忙释疑吧,我都不忍再往下看书了。
    18 条回复    1970-01-01 08:00:00 +08:00
    CoX
        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的输出是怎么回事
    vayn
        2
    vayn  
       2012-05-09 11:38:19 +08:00
    members 是类属性,而非实例属性
    Cofyc
        3
    Cofyc  
       2012-05-09 11:38:36 +08:00
    学 Python 时,记住一句话:"Everything Is an Object"

    一切都是对象,你就明白了。

    这里,类 MemberCounter 也是对象。

    包括类的类型(type)也是对象,type 的 type 是其自身。
    levon
        4
    levon  
    OP
       2012-05-09 11:48:05 +08:00
    @CoX 谢谢回复,我是写入一个文档,然后执行文档的
    levon
        5
    levon  
    OP
       2012-05-09 11:50:15 +08:00
    @vayn 有类属性和实例属性之分吗,你意思是不是我实例化一个类得到一个新的instance后可以为这个实例添加新的属性?
    Cofyc
        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 访问。
    allenm
        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 更菜,如果说错了,欢迎指正。
    levon
        8
    levon  
    OP
       2012-05-09 11:52:09 +08:00
    @Cofyc 哦,是的,我忘记写这句了,实际文档中是有的
    eerie
        9
    eerie  
       2012-05-09 11:54:16 +08:00
    cpp也有static member,不知道楼主啥意思
    agui
        10
    agui  
       2012-05-09 11:56:21 +08:00
    看的是<python基础教程>吧? 我最近也在看,有问题大家可以一起交流下:)
    levon
        11
    levon  
    OP
       2012-05-09 12:05:03 +08:00
    @agui 是的,是这本。

    @eerie你说的static member,这种成员是不是每个实例都是一样的值?

    我知道python就是这样的。书上也有说SmallTalk之父反对这种,说对象特性只允许同一个对象的方法访问。觉得Python这样做破坏了封装的原则。我看得有点模糊,一知半解
    ipoh
        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
    eerie
        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
    bravluna
        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 属性。
    chainchan
        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__属性。
    sampeng
        16
    sampeng  
       2012-05-09 13:31:13 +08:00
    我觉得应该这么理解python
    面向对象,更深的说应该是面向接口。
    任何你使用的对象,包括函数都是接口。只要参数传进来他就不管这个货到底是什么。只要有函数自己需要的接口,就会有正确的行为。

    这是极灵活的。。。。虽然其他的语言也是这么一说,但是python直接作为强制行为了。为什么python类的属性是没有私有一说的。就是这个原因。只要定义了,那就是一个对外的接口
    levon
        17
    levon  
    OP
       2012-05-09 14:20:53 +08:00
    @chainchan 谢谢,你的解释让我有用
    hwywhywl
        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) 则看它如何处理。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5441 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 01:23 · PVG 09:23 · LAX 18:23 · JFK 21:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.