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

关于私有化问题

  •  
  •   sudo987 · 2016-06-21 18:10:40 +08:00 · 3741 次点击
    这是一个创建于 2872 天前的主题,其中的信息可能已经有所发展或是发生改变。

    很简单的一段代码,觉得基类的同名方法应该会被子类覆盖,但是并没有,求解。

    class P(object):
        def __f(self):
            print 'i am P'
        f = __f
        def __init__(self):
            self.f()
    
    class C(P):
        def _P__f(self):
            print 'i am C'
    
    c = C() # i am P
    
    27 条回复    2016-06-22 09:44:16 +08:00
    GreatMartial
        1
    GreatMartial  
       2016-06-21 18:21:24 +08:00 via Android
    小白一枚,昨晚刚看继承与包含,
    https://flyouting.gitbooks.io/learn-python-the-hard-way-cn/content/learn-python-the-hard-way-exercise44.html
    你看一下,能否解决你的问题。
    hitmanx
        2
    hitmanx  
       2016-06-21 18:24:31 +08:00
    f = __f 估计在第一次 evaluate class P 时就被赋值了,不会在后来初始化 class C 时再更改了。

    你可以把 f = __f 去掉,然后在 P.__init__()里直接调用__f()试试
    9hills
        3
    9hills  
       2016-06-21 18:25:09 +08:00
    C 和 P 有同名方法么?没看到啊?
    sudo987
        4
    sudo987  
    OP
       2016-06-21 18:25:29 +08:00 via iPhone
    @GreatMartial 直接说问题在哪儿不好么?
    sudo987
        5
    sudo987  
    OP
       2016-06-21 18:26:58 +08:00 via iPhone
    @9hills 基类中的__f()由于私有化其实是_P__f(),子类有同名方法
    kier
        6
    kier  
       2016-06-21 18:29:50 +08:00
    @sudo987 你这有点想当然啊,又不是外部调用,直接方法调用方法,哪还需要考虑私有?
    sudo987
        7
    sudo987  
    OP
       2016-06-21 18:29:55 +08:00 via iPhone
    @hitmanx 谢谢回复,那肯定可以,不想靠猜测,想要求解。
    sudo987
        8
    sudo987  
    OP
       2016-06-21 18:30:59 +08:00 via iPhone
    @kier 官方文档看到这种例子,不解,于是求问。
    kier
        9
    kier  
       2016-06-21 18:32:45 +08:00
    @sudo987 麻烦吧官方链接发出来看看?
    9hills
        10
    9hills  
       2016-06-21 18:34:52 +08:00
    @sudo987 Python 什么时候多了这种 Magic 。。给个文档我看看
    9hills
        11
    9hills  
       2016-06-21 18:35:45 +08:00
    另外 Python 是没有私有方法的,所有方法都是 Public 的,你再怎么加下划线也没用。。。
    kier
        12
    kier  
       2016-06-21 18:37:05 +08:00
    python 没有严格意义的私有方法,只是在__开头的方法,在外部调用的时候,要改下名调用,但是如果是方法调方法,不需要改名的
    sudo987
        13
    sudo987  
    OP
       2016-06-21 18:38:23 +08:00
    @9hills 求解什么叫私有化?
    sudo987
        14
    sudo987  
    OP
       2016-06-21 18:40:10 +08:00
    严不严格无所谓,我只是不明白这段代码的输出为什么会这样,求解。
    sudo987
        15
    sudo987  
    OP
       2016-06-21 18:41:39 +08:00
    hitmanx
        16
    hitmanx  
       2016-06-21 18:42:41 +08:00
    @sudo987

    class P(object):
    def __f(self):
    print('i am base')

    def __init__(self):
    self.__f()

    class C(P):
    def _P__f(self):
    print('i am derived')

    c = C() # i am P


    输出为 i am derived
    kier
        17
    kier  
       2016-06-21 18:43:43 +08:00
    你再 init 里面调用的是 self.f(),又不是 self.__f(),那肯定是执行 print 'i am P'啦
    9hills
        18
    9hills  
       2016-06-21 18:44:39 +08:00
    @sudo987 你的标题你问我?

    文档里写的很明白:“ Private ” instance variables that cannot be accessed except from inside an object don ’ t exist in Python.

    而且也没有你这种用法。。。下划线没有任何 Magic 和语法含义在里面,你仔细看就明白了
    sudo987
        19
    sudo987  
    OP
       2016-06-21 18:46:14 +08:00
    @hitmanx 自己试过,这种方法可以输出想要的结果,不明白加上 f = __f 后为什么结果不是想要的。
    kier
        20
    kier  
       2016-06-21 18:52:53 +08:00
    >>> def a():
    ... print 'a'
    ...
    >>>
    >>> b = a
    >>> def a():
    ... print 'new a'
    ...
    >>> a()
    new a
    >>> b()
    a
    @sudo987 这个你能理解不?
    sudo987
        21
    sudo987  
    OP
       2016-06-21 19:26:05 +08:00
    自己搞明白了,这个问题跟私有化没有关系,换成普通名字问题依旧,问题出在实例化顺序上, f = __f 存在于基类,属于类变量,且执行时机早于父类的__init__()更早于基类的__init__(),所以其实 f 的指向已经固定了,就是父类的__f(),且在子类没有对 f 的赋值操作,所以,即使子类覆盖了父类的同名方法__f(), f 的指向早就固定在父类的__f()了,所以才有 i am P 的输出。只有 @hitmanx 说对了。
    sudo987
        22
    sudo987  
    OP
       2016-06-21 19:38:56 +08:00 via iPhone
    说错了,更早于子类。
    kier
        23
    kier  
       2016-06-21 20:06:20 +08:00
    其实在 python 里, function 跟数字,字符串是一样的
    比如 a = 1; b = a; a =2; 这时 b 的取值是什么呢,相信你也能一样看出是 1 ,如果把 1,2 换成一个函数体呢?其实效果也是一样的, b 还是原来的函数,类方法也是同样的道理,改了 P.__f ,但是 P.f 还是原来的那个方法,并没有改变

    由于看到 5 楼你的回复,被带偏了,就直接答到私有方法上面去了,但是后来我在 20 楼的回复,就是想表达这么个意思
    好吧,下次我回答问题,一定好好看看题目!
    sudo987
        24
    sudo987  
    OP
       2016-06-21 20:52:23 +08:00
    @kier 嗯嗯。
    happywowwow
        25
    happywowwow  
       2016-06-21 21:39:23 +08:00
    @9hills
    p = P()
    print dir(p)
    print dir(c)
    你可以看到['_P__f'......]
    sudo987
        26
    sudo987  
    OP
       2016-06-21 23:24:14 +08:00 via iPhone
    @9hills 回答个问题跟放炮似的,回答的对也就不说什么了,况且你的回复跟我的问题完全不搭边,呵呵,“你的标题你问我?”,会说话么?你爱答不答,没人逼你,别在这儿影响我心情。
    qian19876025
        27
    qian19876025  
       2016-06-22 09:44:16 +08:00
    我晕 这标题 差点以为是 360 的人问私有化
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2264 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:41 · PVG 14:41 · LAX 23:41 · JFK 02:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.