在__init__()对 self 重新赋值的疑惑 - V2EX
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
sudo987
V2EX    Python

在__init__()对 self 重新赋值的疑惑

  •  
  •   sudo987 2016-06-16 14:45:09 +08:00 3828 次点击
    这是一个创建于 3410 天前的主题,其中的信息可能已经有所发展或是发生改变。

    既然 self 指的是实例,那么在__init__()中对 self 重新赋值,比如, self = 4.21 ,然后对实例对象进行打印,结果应该打印出 4.21 这个值,可实验结果却不是。

    class A(int): def __init__(self, t): self = 4.21 a = A(34) print a # a = 34,而不是 4.21 

    求解。

    19 条回复    2016-06-17 05:55:01 +08:00
    hitmanx
        1
    hitmanx  
       2016-06-16 15:16:38 +08:00
    python 我也是学习中,说错请见谅。
    1. self 相当与其它语言里的 this 指针吧, self=4.21 本来就是有问题的语句.
    2. 4.21 本来就不是浮点数,你注释里写的期待值是 4.21 肯定是不对的,当成功时应该期待的是 4 而不是 4.21
    3. 你需要显示给父类,也就是这里的 int 类进行初始化
    4. int 在 python 里是 immutable type,在这种情况下初始化父类时需要用__new__而不是__init__

    以上这些你稍微拿关键字搜一下就能出来了:
    http://stackoverflow.com/questions/3238350/subclassing-int-in-python
    http://stackoverflow.com/questions/2673651/inheritance-from-str-or-int

    #  int is immutable so you can't modify it after they are created, use __new__ instead

    class TestClass(int):
    def __new__(cls, *args, **kwargs):
    return super(TestClass, cls).__new__(cls, 4.21)

    print TestClass(34)
    SErHo
        2
    SErHo  
       2016-06-16 15:16:59 +08:00
    对 self 赋值的时候,其实是创建了一个新的局部变量,比如执行以下代码:

    >>> class A(int):
    ... def __init__(self):
    ... print id(self)
    ... self = 42
    ... print self
    ... print id(self)
    ...
    ...
    ...
    >>> a = A()
    4543469472
    42
    140376639849864

    给个链接: http://stackoverflow.com/questions/1015592/why-is-self-in-python-objects-immutable
    sudo987
        3
    sudo987  
    OP
       2016-06-16 15:30:34 +08:00
    谢谢二位仁兄的回答,可能是我描述不清,是这样的,我们都知道__init__()是实例创建后执行的第一个方法,并且 python 没有赋值时的变量审查,所以我觉得在__init__()里对 self 赋什么值都是可以的,所以我想在__init__()对 self 进行赋值,让 self 变成一个完全不同的东西,诸如从 int 编程 float ,我觉得应该是可以的,但是结果却不是这样,求解。
    SErHo
        4
    SErHo  
       2016-06-16 15:37:37 +08:00
    @sudo987 我的答案你看没有啊??你对 self 赋值的时候,赋值的 self 已经不是原来的 self 了。
    sudo987
        5
    sudo987  
    OP
       2016-06-16 15:41:23 +08:00
    @SErHo
    ```
    class A(int):
    pass
    a = A(45)
    print a # 45

    class B(int):
    def __init__(self, t):
    self = 45
    b = B(2)
    print b # 2 而不是 45
    ```
    sudo987
        6
    sudo987  
    OP
       2016-06-16 15:42:54 +08:00
    @SErHo 稍等,我再看下。
    sudo987
        7
    sudo987  
    OP
       2016-06-16 16:05:45 +08:00
    @SErHo 谢谢提供链接,链接里给的例子很到位,”__new__()是真正的构造器,__init__()只是个初始化器“,这个说的比较好,可是具体“为什么”没有给出,而且您给出的通过 id()判断 self 似乎和我的问题关系不大,重新给 self 赋值,相当于改变 self 指针的指向,从 A 实例变成指向 42 ,可是,不管在不在__init__()做操作, id(self)前后的值肯定是不一样的。我不明白的是既然可以对 self 动态赋值,为什么不能改变 self 的指向(在 new 里面肯定可以,因为他是生成实例的地方),求解。
    srlp
        8
    srlp  
       2016-06-16 16:07:10 +08:00
    self 已经成为同名局部变量。
    srlp
        9
    srlp  
       2016-06-16 16:08:53 +08:00
    没有办法改变 self 的“指向”,因为此处没有类似 c 语言里面类似 *ptr 那种 dereference 操作符。
    21grams
        10
    21grams  
       2016-06-16 16:29:02 +08:00 via Android
    self 也能乱改的?
    sudo987
        11
    sudo987  
    OP
       2016-06-16 16:33:07 +08:00
    @21grams 不关注实用性,只关注可能性。
    sxmman
        13
    sxmman  
       2016-06-16 16:41:34 +08:00
    @sudo987 为什么是 new 里面创建实例,因为涉及到元类 metaclass 的概念,任何对象的都是从 type 继承过来的,如果申明某一个类为子类的 metaclass ,且在父类中重载 __new__方法的话,可以控制实例的生成,但是其实还是 super(Parent, cls).__new__(cls)得到的,所以任何类的 parent 其实都是 type 。
    至于为什么 init 中改变 self 本身无效,我猜是这样的,传入的 self 是一个变量,他的值就是实例的指针,也就是 c 中的**p ,如果改变他的值,并没有把 *p 的值修改,所以修改无效。
    cxyfreedom
        14
    cxyfreedom  
       2016-06-16 16:55:33 +08:00
    你__init__中的 self 只是同名的变量,你并没有对实际的对象进行改变。本身对象的 self 应该不能修改吧
    xiaolee59
        15
    xiaolee59  
       2016-06-16 17:34:48 +08:00
    所有在局部作用域内的重新赋值(其实是名字和值的绑定)都会使解释器将该名字看做是当前局部作用域内的局部变量,你给 self 赋值,“ self ”这个名字在__init__内就绑定到了 4.21 这个值,然而, self 的有效生命周期仅仅存在于__init__内,对传进来的对象无影响。
    sudo987
        16
    sudo987  
    OP
       2016-06-16 19:50:19 +08:00
    @sxmman 多谢回复,纠正一下,任何类都是一个 type 这个准确,可任何对象都是从 type 继承来的,这个不对, object 是继承链的顶端,连 type 都是它的子类。
    sudo987
        17
    sudo987  
    OP
       2016-06-16 19:52:15 +08:00
    @sxmman
    object.__class__ = <type 'type'>
    type.__bases__ = (<type 'object'>,)
    RTNelo
        18
    RTNelo  
       2016-06-16 21:28:13 +08:00
    文档中的解释:
    https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy
    注意 Callable types 中 User-defined methods 的说明。

    另外建议把 Data Model 这一章看完。
    haoc
        19
    haoc  
       2016-06-17 05:55:01 +08:00
    我的理解是: self 是 instance 的 reference 。在__init__ scope 里你 self 行值,所以在__init__中有一 local 的 self 。所以最後的果是 instance 本身有被改。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1204 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 17:45 PVG 01:45 LAX 10:45 JFK 13:45
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86