Python 发现个奇怪知识,类属性不被实例化修改,即可被外部修改 - 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
llsquaer
V2EX    Python

Python 发现个奇怪知识,类属性不被实例化修改,即可被外部修改

  •  
  •   llsquaer 2022-03-25 19:33:37 +08:00 4086 次点击
    这是一个创建于 1362 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天使用 selenium 使用拖拽效果,发现异常的慢.网上一顿搜索,发现解决办法是修改源码控制间隔的属性值..

    这样太不友好了.直接全局改了.后来想看能不能外部写一个继承方法来做,看了源码后,还是放弃,水平有限.于是想的通过外部修改.

    于是做了一下实验.

    代码如下. 备注有返回值

    class AAA(): DEP = 0 def get(self): return self.DEP print(AAA.DEP) # 0 AAA.DEP = 5 # 修改默认属性 ex_1 = AAA() # 实例化 ex_1 print(ex_1.get()) # 5 AAA.DEP = 10 # 再次修改默认属性 print(ex_1.get()) # 10 ex_1.DEP = 15 # ex_1 修改实例属性 print(ex_1.get()) # 15 AAA.DEP = 12 # 再次修改默认属性 print(ex_1.get()) # 15 被上次实例化修改属性后,类属性不再被修改,即返回 15 ex_2 = AAA() # 实例化 ex_2 print(ex_2.get()) # 12 上段 ex_2 实例化之前前修改的值 AAA.DEP = 20 # 修改原始属性 print(ex_2.get()) # 20 ex_2.DEP = 30 print(ex_2.get()) # 总结,类实例化后若原始属性不被修改 ,均可被外动态修改 

    总结,类实例化后若原始属性不被修改 ,均可被外动态修改

    后来再次实验,如果被 init 初始化,值也不能被修改了

    class AAA(): DEP = 0 def __init__(self): self.DEP=10 # 被 init 初始化后,不能被修改了 def get(self): return self.DEP 

    感觉奇奇怪怪的知识增加了..

    这么说,再次使用 selenium 不用使用 time.sleep 来控制了吧. 还没试,先分享下新发现.

    25 条回复    2022-07-22 12:33:37 +08:00
    zagfai
        1
    zagfai  
       2022-03-25 19:40:35 +08:00
    Python 就是太灵活了,所以说做大型项目架构的严谨性更为重要
    alphanow
        2
    alphanow  
       2022-03-25 19:55:22 +08:00   1
    建议读一读 python 官方教程中的 classes 一节。类变量和实例变量并不等价,类变量在所有实例中共享,在通过实例查找变量时实例变量优先于类变量被获取。

    把类变量用实例变量覆盖的方式不如通过子类覆写类变量的方式安全。
    Nitroethane
        3
    Nitroethane  
       2022-03-25 19:59:59 +08:00 via iPhone   2
    你是把类变量喝对象变量混淆了。看这个 https://stackoverflow.com/a/5690920
    mangoDB
        4
    mangoDB  
       2022-03-25 20:18:12 +08:00
    楼主看下 3# 答案,解释很清晰。
    Dganzh
        5
    Dganzh  
       2022-03-25 20:36:04 +08:00
    好像也没啥问题,实例属性覆盖类属性了。
    主要是 Python 太灵活,ex_1.DEP = 15 ,这样可以动态创建实例属性。
    ClericPy
        6
    ClericPy  
       2022-03-25 21:00:16 +08:00
    省流一句话:
    self.xxx 从对象作用于里找 xxx 属性 /方法, 没找到, 去类作用域里面找, 找到了; self.xxx 赋值以后, 从对象作用域里找到了, 就不去类作用域找了
    rrfeng
        7
    rrfeng  
       2022-03-25 21:21:30 +08:00 via Android
    上面解释很清晰了。但是可以在外面改类内的变量就很奇怪…
    imn1
        8
    imn1  
       2022-03-25 21:22:10 +08:00
    只会在同一个引用链条上起作用,分别两个地方引用,改变其中一个,另一个还是原值,相当于作用域不同

    或者试试外部改变后,reload 一次看看

    “总结,类实例化后若原始属性不被修改 ,均可被外动态修改”
    这句就不评价了,前面几楼都讲太多了

    AAA.DEP=30
    a=AAA()
    a.DEP=20
    print(a.DEP)
    print(AAA.DEP)
    imn1
        9
    imn1  
       2022-03-25 21:30:22 +08:00
    @rrfeng #7
    因为 python 几乎全部变量都是引用,只有 int/float/complex/string 等少量类型不是
    外部改变实际上只是改变了引用的指向,我是这样理解的,但也不知道对不对
    反正我也不知道如何用原生语法定义一个不可变(只读)的常量
    JeffGe
        10
    JeffGe  
       2022-03-25 21:43:59 +08:00 via Android
    @imn1 不用几乎,Python 里面所有的变量赋值都是共享对象传递
    https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing
    beastk
        11
    beastk  
       2022-03-26 00:07:10 +08:00 via iPhone
    和调用顺序有关,本来就是这样
    lux182
        12
    lux182  
       2022-03-26 01:27:36 +08:00
    个人感觉大型项目还是不敢用 python ,如此灵活的语法太容易写出致命 bug
    LeeReamond
        13
    LeeReamond  
       2022-03-26 02:35:40 +08:00   2
    @lux182 解决方案:招募正经程序员
    vicalloy
        14
    vicalloy  
       2022-03-26 07:51:40 +08:00
    monkey patch 这 python 里面也算是挺常规的操作。
    est
        15
    est  
       2022-03-26 09:19:00 +08:00
    这还不算啥,你还可以在运行中改方法、改方法的参数,改方法内部的变量。
    mongodb
        16
    mongodb  
       2022-03-26 09:32:53 +08:00   2
    Python 太灵活是真的,但拜托你们也把文档读完啊……
    llsquaer
        17
    llsquaer  
    OP
       2022-03-26 11:18:02 +08:00
    @est 之前也干过运行中从外部改方法..但是改的时候都是实例化后修改的实例方法.. 现在是突然想到直接改类默认属性的想法..所以才实验一番..
    其实 2 楼 3 楼已经说明了原因.. 只是忘记了在类变量内部搜索方式了..因为平时很少这么用的场景..
    实际上实例化后也是可以获取到初始属性的 使用 __class__ 方法
    llsquaer
        18
    llsquaer  
    OP
       2022-03-26 11:32:42 +08:00
    @alphanow
    @Nitroethane

    是的哈..一说就突然想起来了 哈哈
    kilasuelika
        19
    kilasuelika  
       2022-03-27 10:29:49 +08:00
    我寻思这其实有点像 C++中的静态变量?同样可以在没有实例化的情况下修改:
    ```
    #include <iostream>

    struct AAA {
    static int DEP;

    int get()const {
    return this->DEP;
    };
    };
    int AAA::DEP = 0;
    int main()
    {
    AAA::DEP = 5;
    std::cout << AAA::DEP << std::endl; //5

    AAA a;
    std::cout << a.get() << std::endl; //5

    a.DEP = 15;
    std::cout << a.get() << std::endl; //15
    }
    ```
    不过有个区别是`this->DEP`与`DEP`是同一个变量,所以这里在 C++中是不行的:
    ```
    AAA.DEP = 12 # 再次修改默认属性
    print(ex_1.get()) # 15 被上次实例化修改属性后,类属性不再被修改,即返回 15
    ```
    C++里面后一句必然是 12 。
    AV1
        20
    AV1  
       2022-03-27 15:29:11 +08:00
    @kilasuelika
    我写 python 从来不用 class ,也是觉得不可思议。
    python 的 self.xxx ,有可能指向静态成员(类变量),也可能指向实例成员(对象变量)。
    如果实例化的对象时没有初始化实例成员,就会使用静态成员作为默认值。
    kilasuelika
        21
    kilasuelika  
       2022-03-27 23:29:55 +08:00 via Android
    @DOLLOR 我也是第一次听说 python 中的这种情况。感觉这个特性有点容易导致问题
    neoblackcap
        22
    neoblackcap  
       2022-03-28 02:40:50 +08:00
    如果多写 Python 就会习惯了,这设计就是这样的。甚至还有用这个特性去替代单例模式。
    lanlanye
        23
    lanlanye  
       2022-03-28 03:44:15 +08:00 via iPhone
    所以不建议水平不够的人写 Python ,更不建议和水平不够的人合作 Python 项目
    语言没有约束,就只有靠程序员自己去约束了
    hhhhhh123
        24
    hhhhhh123  
       2022-03-28 10:04:23 +08:00
    我没太看懂你想要啥 你可以试试这个
    class AAA:
    DEP = 0

    def get(self):
    return self.DEP

    def set(self, x):
    return self.DEP + x


    print(AAA().set(12)) # 12
    print(AAA().get()) # 0
    Tyler1989
        25
    Tyler1989  
       2022-07-22 12:33:37 +08:00 via Android
    @beastk 站长,看一下 tg
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4279 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 10:08 PVG 18:08 LAX 02:08 JFK 05:08
    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