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

今天不小心踩了可变类型的坑

  •  
  •   Vegetable · 2019-02-21 14:50:49 +08:00 · 3255 次点击
    这是一个创建于 2106 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class Example:
        
        # 坑
        container = {}
        
        def __init__(self):
            # do init
            pass
        def result(self):
            if self.container:
                return self.container()
            self.container["a"] = self._a()
            self.container["b"] = self._b()
            return self.container
        def _a(self):
            # fetch data
            return "a"
        
        def _b(self):
            # fetch data
            return "b"
        
    

    今天用了一个这样的结构来处理部分数据.然后就出现了第二个实例返回的结果和上一个一样的情况. 反思了一下自己在写代码的时候根本没注意到这个 container 在两个实例里可能会指向同一个地址的问题.写 python 两年多一直在很小心 list 和 dict 作为参数时避免采坑,没想到今天换了个地方踩了一下,不知道别人是不是了解这个坑,发出来给大家看看吧

    20 条回复    2019-02-21 19:24:47 +08:00
    j0hnj
        1
    j0hnj  
       2019-02-21 15:05:58 +08:00
    这...是常识吧,楼主写两年多 Python 写的都是啥?
    freakxx
        2
    freakxx  
       2019-02-21 15:08:14 +08:00
    静态变量

    不过确实有很大部分直接入 python 并不了解这个东西。
    whoami9894
        3
    whoami9894  
       2019-02-21 15:10:03 +08:00   ❤️ 2
    因为类变量是实例共享的,不可变类型修改时会修改实例变量,可变类型就是这种情况

    return self.container() 这里多了对括号
    araraloren
        4
    araraloren  
       2019-02-21 15:13:36 +08:00
    可变类型? 静态变量?
    9hills
        5
    9hills  
       2019-02-21 15:14:58 +08:00 via iPhone   ❤️ 1
    尽量避免使用类变量,使用大写定义常量,只读不写。

    类变量也有并发冲突问题。
    liu19931020
        6
    liu19931020  
       2019-02-21 16:47:04 +08:00
    lolizeppelin
        7
    lolizeppelin  
       2019-02-21 16:57:35 +08:00
    ....两年真白写了

    我估计单例你都没写过......
    Orenoid
        8
    Orenoid  
       2019-02-21 17:03:32 +08:00
    @liu19931020 请问这是什么书
    windfarer
        9
    windfarer  
       2019-02-21 17:06:16 +08:00 via Android
    我在刚入行半年的时候,就修过之前老哥留下的这样的 bug= =
    leoli
        10
    leoli  
       2019-02-21 17:17:20 +08:00
    这也不是楼主所说的 "可变类型的坑" 吧。这都能理解错,楼主还是要严谨点。
    liu19931020
        11
    liu19931020  
       2019-02-21 17:18:26 +08:00   ❤️ 1
    @Orenoid Python 基础教程(第三版)
    zwzmzd
        12
    zwzmzd  
       2019-02-21 17:20:07 +08:00 via iPhone   ❤️ 1
    你需要的是把 self.container 变量定义在__init__函数中,和可变类型没关系
    cyspy
        13
    cyspy  
       2019-02-21 17:28:06 +08:00
    兄弟估计没学过 cpp 或者 java,面向对象底子不够
    huahuajun9527
        14
    huahuajun9527  
       2019-02-21 17:34:45 +08:00
    这应该怪 类属性 跟 实例属性 没搞懂
    xpresslink
        15
    xpresslink  
       2019-02-21 17:45:19 +08:00
    按理说两年了不应该还踩这个坑啊。再说了这个也不 可变类型的坑,
    明显就是类变量和实例变量的概念和区别没弄明白。

    你这个需求下创建实例变量应该把放到 init 方法中。
    class Example:

    ◇◇◇◇def __init__(self):
    ◇◇◇◇◇◇◇◇# do init
    ◇◇◇◇◇◇◇◇self.container = {}
    ◇◇◇◇◇◇◇◇pass
    freakxx
        16
    freakxx  
       2019-02-21 17:51:45 +08:00
    我觉得某楼也不必这么说楼主,

    这个东西,就是点与面的问题,没必要把话说绝。
    zst
        17
    zst  
       2019-02-21 17:55:34 +08:00 via Android
    老实说 Python 这个确实是个坑.......不知道设计的时候咋想的,所以一般丢到 init 里面去比较好
    wangxiaoaer
        18
    wangxiaoaer  
       2019-02-21 17:58:18 +08:00 via Android
    我 Python 不熟,但这个跟可变类型有啥关系啊?看起来是成员变量跟静态变量的问题。
    shm7
        19
    shm7  
       2019-02-21 19:22:37 +08:00 via iPhone
    lz 从 java 来的吧; python 里面用 a, b = a(), b() 不需要写什么 pojo
    shm7
        20
    shm7  
       2019-02-21 19:24:47 +08:00 via iPhone
    的确和可变类型没啥关系,恐怕 java 也没写好,静态的 class 的属性和 obj 的属性用法都是一致的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3265 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:00 · PVG 21:00 · LAX 05:00 · JFK 08:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.