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
huanghua123
V2EX  ›  Python

大家写 python 的时候不会觉得 self 有点冗余吗

  •  
  •   huanghua123 · 2016-05-23 16:21:42 +08:00 · 7530 次点击
    这是一个创建于 3105 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写这样一个简单的类用到 n 多 self ,个人觉得有点冗余,大家什么感觉?我也是初学,或者有好的方法可以避免?

    class VendingMachine:
        """A vending machine that vends some product for some price."""
        def __init__(self,stockName,stockPrice):
            self.stockName = stockName
            self.stockPrice = stockPrice
            self.stockNumber = 0
            self.balance = 0
    
        def vend(self):
            if self.stockNumber == 0:
                return "Machine is out of stock."
            elif self.balance < self.stockPrice:
                return 'You must deposit $' + str(self.stockPrice - self.balance) + ' more.'
            else:
                self.stockNumber -= 1
                change = self.balance - self.stockPrice;
                self.balance = 0
                if change == 0:
                    return 'Here is your candy.'
                else:
                    return 'Here is your candy and $'+ str(change) +' change.'
    
    
        def deposit(self,amount):
            self.balance += amount
    
            if(self.stockNumber == 0):
                return 'Machine is out of stock. Here is your $' + str(self.balance) + '.'
    
            return "Current balance: $" + str(self.balance)
    
        def restock(self,stockNumber):
            self.stockNumber += stockNumber
            return "Current candy stock: " + str(self.stockNumber)
    
    50 条回复    2016-05-25 10:18:16 +08:00
    SlipStupig
        1
    SlipStupig  
       2016-05-23 16:24:42 +08:00
    self 是隐含调用类似 this->obj 这种语法,如果不想用 self 可以声明成静态成员函数,你就不需要写了,同样你无法调用其它非静态成员
    BOYPT
        2
    BOYPT  
       2016-05-23 16:27:51 +08:00
    要不去学 perl 吧(坏笑
    NullMan
        3
    NullMan  
       2016-05-23 16:34:00 +08:00   ❤️ 5
    建议:
    1, 变量采用下划线, 跟 Python 核心类库一致.
    2, stockNumber 改为 number_of_stocks. 不看完你代码, 还以为指的的股票代码呢.
    3, VendingMachine 改为 AutoStockRobot.
    4, balance 存放到你另外一个类(Account).
    5, 跟股票相关的, 放到另外一个类, 比如 Stock.
    6, AutoStockRobot 就有 account, stocks 这俩主要变量, 和三个那 restock, deposit, vend 这三动作.

    总结: 你至少要有三个类, AutoStockRobot, Account, Stock, 单一职责原则. 程序是对现实的模拟, 你现实是怎么样, 程序就能怎么样. 你现实中为人处事很有条理, 规矩, 那么你程序也能写得这么好.
    clino
        4
    clino  
       2016-05-23 16:39:07 +08:00
    我觉得这是个挺好的做法啊,把面向对象的做法明白展示出来了
    其实 lua 也是,不过 lua 可以有语法糖来省掉函数声明里的参数
    huanghua123
        5
    huanghua123  
    OP
       2016-05-23 16:39:12 +08:00
    @BOYPT 其实我也想感受下七周七语言。。
    huanghua123
        6
    huanghua123  
    OP
       2016-05-23 16:39:41 +08:00
    @NullMan 感谢建议
    huanghua123
        7
    huanghua123  
    OP
       2016-05-23 16:41:01 +08:00
    @clino 意思上确实清晰很多。实际上写起来,却有些繁琐。各有取舍吧
    NullMan
        8
    NullMan  
       2016-05-23 16:45:29 +08:00
    @huanghua123 No, No, 写起来, 看起来繁琐, 但是你读起来, 维护起来, 轻松得不得了. 不信, 你试试按我的方式写一个, 然后把你我的版本, 给你同事看看. 看看他会觉得哪个最舒服?

    如果你程序真的就如上那么简单而且. 那么把这三个类, 写到一个文件里. 那么在编写方面. 只比你的版本繁琐那么一丢丢, 只有一丢丢而已. 但是其他方面, 远远超过你的版本了.

    如果是大系统里的一部分, 相信, 拆开来搞.


    另外, 你这程序, 看起来是在搞全自动炒股机器人? 可否带带我呀?
    huanghua123
        9
    huanghua123  
    OP
       2016-05-23 16:50:44 +08:00
    @NullMan 我并不是指面向对象繁琐,我是指 self 繁琐,不过也还接受,纯粹吐槽。这其实只是 berkeley 的 homework 。。
    NullMan
        10
    NullMan  
       2016-05-23 16:59:42 +08:00
    @huanghua123 坏坏地说一句: 伯克利的学生写的程序这么烂, 让我这一个初中文化的程序员满满的成就感.

    逃 :)
    aaaron7
        11
    aaaron7  
       2016-05-23 17:09:40 +08:00
    我也习惯用类似这样的驼峰命名,被 IDE 各种 warning ……让我改小写。。
    huanghua123
        12
    huanghua123  
    OP
       2016-05-23 17:10:14 +08:00
    @NullMan 。。我不是 berkeley 的。你这么说我就不服了。这明明是个自动售货机,你非要说成炒股机器人...
    huanghua123
        13
    huanghua123  
    OP
       2016-05-23 17:11:00 +08:00
    @aaaron7 肯定是 java 过来的。。
    NullMan
        14
    NullMan  
       2016-05-23 17:13:32 +08:00
    @huanghua123 我勒个去, 居然是自动售货机..... 更坏坏说一句: 你这侧面证明了你写得多**, 居然能让我认为是个自动炒股机器人的部件咧....
    huanghua123
        15
    huanghua123  
    OP
       2016-05-23 17:14:06 +08:00
    """A vending machine that vends some product for some price.""" 你在逗我
    NullMan
        16
    NullMan  
       2016-05-23 17:14:52 +08:00
    @huanghua123 哦, 我说写这程序的人.
    ma125125t
        17
    ma125125t  
       2016-05-23 17:33:47 +08:00
    @NullMan 说的没错,看这变量名取的确实不明所以。 stockName 理解为股票名, stockPrice 理解为股票价格是很正常的了。代码写得好不好,能让别人第一时间上手是很重要的一点。
    jiang42
        18
    jiang42  
       2016-05-23 17:45:44 +08:00 via iPhone
    感觉 class 的注释很多余。。。
    lightening
        19
    lightening  
       2016-05-23 17:50:53 +08:00
    你的编辑器会自动帮你写的吧,一般你写 def<tag> 他就出来了。
    scriptfans
        20
    scriptfans  
       2016-05-23 17:54:32 +08:00
    不加 self 的话,你让解释器如何分辨你是想声明局部变量呢,还是想访问属性?
    congeec
        21
    congeec  
       2016-05-23 17:54:56 +08:00 via iPhone
    写起来并不繁琐,你需要 vim
    cxh116
        22
    cxh116  
       2016-05-23 17:57:38 +08:00
    有比较好一点,在 ruby 里面这是一个比较容易踩的坑.

    puts name,这个 name 变量,如果没有,则从自动从 self 对象上面找.
    习惯后,就有可能 name = 'test' 这样写,但这样赋值,变成给 name 本地变量赋值,而不是实例属性赋值,有点坑.
    a412739861
        23
    a412739861  
       2016-05-23 18:19:37 +08:00
    @aaaron7 Objective-C 的风格么,不过我感觉驼峰的写法不容易读……还是下划线的好读。当然 Apple 里面都是驼峰,自然为了一致,都写驼峰了。
    introom
        24
    introom  
       2016-05-23 18:22:01 +08:00 via Android
    self 是很冗余,一个语言不是什么都好可惜现在回不去了,不可能说我们把 self 作为一个关键字。
    ayaseangle
        25
    ayaseangle  
       2016-05-23 18:40:02 +08:00   ❤️ 1
    主要是 python 的 oo 特性是随着后期发展慢慢加进去的,所以看上去不是那么和谐。。。
    Mutoo
        26
    Mutoo  
       2016-05-23 18:51:12 +08:00
    python 语言在发明的时候就规定一件事只有一种做法( There's Only One Way To Do It )。像 java 那样,省略或不省略 this 两种写法就违背了这个守则,详见:
    https://wiki.python.org/moin/TOOWTDI
    eric6356
        27
    eric6356  
       2016-05-23 19:16:03 +08:00
    Explicit is better than implicit.
    https://www.python.org/dev/peps/pep-0020/
    L2AKnG8GXx60bc6P
        28
    L2AKnG8GXx60bc6P  
       2016-05-23 20:02:30 +08:00
    php 的 this 和 self 岂不美哉?
    SlipStupig
        29
    SlipStupig  
       2016-05-23 20:24:58 +08:00
    @scriptfans 用 this 或者用声明 thiscall 修饰,在虚拟机里面采用调用方来维持堆栈平衡, python 设置的时候就没想过用程序员来平衡虚拟机堆栈
    tempdban
        30
    tempdban  
       2016-05-23 20:47:30 +08:00 via Android
    我还觉得$贼傻逼呢,该用不还是得用
    weyou
        31
    weyou  
       2016-05-23 23:21:07 +08:00
    加上 self 更加清晰, C++里面不需要 this ,往往要用别的方式来表明这是个类成员变量,比如加上 m_前缀。
    incompatible
        32
    incompatible  
       2016-05-23 23:24:21 +08:00 via iPhone
    @Mutoo 你说的并不能解答楼主的问题,楼主问的是 self 是否冗余。假设 Java 显示规定必须使用或必须不使用 this.来调用成员方法或引用成员变量,看起来显然比 python 清爽多了。
    msg7086
        33
    msg7086  
       2016-05-23 23:48:45 +08:00
    觉得繁琐写 Ruby 去啊。
    Python 的精髓就是繁琐……
    zijikai
        34
    zijikai  
       2016-05-24 00:29:43 +08:00
    对于新手来说,至少逻辑上理解起来轻松多了。
    noli
        35
    noli  
       2016-05-24 01:55:15 +08:00 via iPhone
    在 python 中 self 是必须的,否则二义性会毁掉这门语言。我很奇怪居然有人说 self 是冗余的?
    SharkIng
        36
    SharkIng  
       2016-05-24 02:01:22 +08:00 via iPhone
    self 主要是方便日后使用 class 里面的变量 感觉有点像 java 里面的 public 变量
    markx
        37
    markx  
       2016-05-24 02:06:37 +08:00
    @ma125125t 看到类名是 VendingMachine , 你就该知道这个跟股票没关系了。
    ligyxy
        38
    ligyxy  
       2016-05-24 04:43:57 +08:00
    居然不止一个人说变量名不明确,心疼楼主
    jamiesun
        39
    jamiesun  
       2016-05-24 07:01:50 +08:00
    self,这是一个必须的东西,也是 python 严谨性的一个体现
    jamiesun
        40
    jamiesun  
       2016-05-24 07:04:25 +08:00
    不喜欢 self ,你可以用 this 啊

    class A:
    ...: def __init__(this):
    ...: print this.__class__
    7jmS8834H50s975y
        41
    7jmS8834H50s975y  
       2016-05-24 07:08:54 +08:00
    我觉得 java 方法调用的模式就比较好.
    cc7756789
        42
    cc7756789  
       2016-05-24 07:27:45 +08:00
    你是没用过 go 的错误处理吧。如果你希望其他语言像 CoffeeScript 一样把 JS 的括号都省了,那么还是转行算了,代码的清晰准确比多写几个跟踪到数据的指针变量符号重要多了。
    KyL
        43
    KyL  
       2016-05-24 09:26:17 +08:00
    self 是程序员自己起的一个变量名,它之所以能起到 self 的作用,只是因为它是类方法的第一个参数。你可以把 self 改成任意变量名。
    我觉得确实有些多此一举,更好的方法是把 self 设为 py 的一个关键字,就像 C++/Java 中的 this 一样。
    realpg
        44
    realpg  
       2016-05-24 09:31:22 +08:00
    那个,你把 stockNumber 改成 inStockCount 就没歧义了

    number 单独使用并没有计数的意思,或者说无法强调计数 in stock 和 stock 是两个完全不同的概念
    RqPS6rhmP3Nyn3Tm
        45
    RqPS6rhmP3Nyn3Tm  
       2016-05-24 10:11:47 +08:00
    IDE 都自动搞定了,读起来容易很多
    ChiangDi
        46
    ChiangDi  
       2016-05-24 10:15:18 +08:00 via Android
    这是个历史缺陷,作者都说了
    2owe
        47
    2owe  
       2016-05-24 11:52:03 +08:00
    兼顾便利性和可读性是坠吼滴!只能偏袒一方的话,可读性优先。
    robinshi2010
        48
    robinshi2010  
       2016-05-24 13:51:13 +08:00
    @NullMan 觉得建议不错。感谢。
    stevenhu888
        49
    stevenhu888  
       2016-05-24 14:06:03 +08:00
    @NullMan 老兄所言甚是
    misaka15
        50
    misaka15  
       2016-05-25 10:18:16 +08:00
    类似于 Swift 一样,省略掉 self ,可读性比较差
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   951 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:34 · PVG 06:34 · LAX 14:34 · JFK 17:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.