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

Python 的传址和传值疑问

  •  
  •   qsnow6 · 2017-02-21 18:47:40 +08:00 · 2606 次点击
    这是一个创建于 2838 天前的主题,其中的信息可能已经有所发展或是发生改变。
    import random
    
    
    class MyFun(object):
    
        def __getattr__(self, key):
            if key == 'random':
                return random.random()
            else:
                pass
    
    f = MyFun()
    f.random
    
    
    

    如上代码

    如何把 f.random 传给一个变量,比如a,然后以后调用 a 就执行 f.random?

    试过浅拷贝、深拷贝都没用。。

    第 1 条附言  ·  2017-02-21 19:58:30 +08:00

    是这样,这个类是一个库里随机生成 UserAgent 的方法 ua.random

    我有一个爬虫,里面的变量是写好的,比如 self.user_agent

    爬虫每次请求都会把self.user_agent作为自己的 User-Agent

    所以我就想让把ua.random 传给self.user_agent,这样,就可以不变更原来的代码的情况下,实现自动更换useragent

    原来的 ua.random 的实现就是通过 getattr 来实现的,发现无论是深拷贝还是浅拷贝,倒过去的是值,没法直接引用ua.random

    self.user_agent = ua.random
    

    UPDATE 直接在原来的基础上套了一个类,也算是实现了;)

    class MyFun(object): 
    
    def __repr__(self): 
    
    from fake_useragent import UserAgent 
    ua = UserAgent() 
    return ua.random 
    f = MyFun()
    
    24 条回复    2017-02-21 22:12:22 +08:00
    cheetah
        1
    cheetah  
       2017-02-21 18:52:22 +08:00
    你是想每次使用 a 的时候产生一个新随机数?

    ```
    >>> a
    0.14750847086722485
    >>> a
    0.822349231203261
    ```

    这样?
    qsnow6
        2
    qsnow6  
    OP
       2017-02-21 18:53:06 +08:00
    @cheetah 对啊~~`
    qsnow6
        3
    qsnow6  
    OP
       2017-02-21 18:54:05 +08:00
    @cheetah 应该怎么传
    cheetah
        4
    cheetah  
       2017-02-21 18:57:39 +08:00
    @qsnow6 我认为做不到。坐等楼下黑科技。
    binux
        5
    binux  
       2017-02-21 19:01:34 +08:00
    ```
    In [6]: class A():
    ...: def __repr__(self):
    ...: return str(random.random())
    ...: a = A()
    ...:

    In [7]: a
    Out[7]: 0.313638352347

    In [8]: a
    Out[8]: 0.00887313470731
    ```
    cheetah
        6
    cheetah  
       2017-02-21 19:04:33 +08:00
    @binux 这个 a 只能用来打印了 = =
    qsnow6
        7
    qsnow6  
    OP
       2017-02-21 19:06:27 +08:00
    @binux 在不修改他原来的类的情况下,有没有办法引用他这个 f.random
    binux
        8
    binux  
       2017-02-21 19:08:29 +08:00
    @cheetah #6 挨个写, __add__,__str__, __eq__ ...
    因为 LZ 并没有说「调用 a 」是什么意思,比如 b = a ,这是在拷贝 a 还是在调用 a ?
    binux
        9
    binux  
       2017-02-21 19:09:45 +08:00
    @qsnow6 #7 这是一个 XY 问题
    Allianzcortex
        10
    Allianzcortex  
       2017-02-21 19:12:29 +08:00
    你的 __getattr__ 是做什么的。。。我觉得按照描述是做不到,但如果不一致性要求的话可以试试用 __call__() 来把类模型为函数:

    ```
    import random


    class MyFun(object):
    def __getattr__(self, key):
    if key == 'random':
    return random.random()
    else:
    pass

    def __call__(self):
    return random.random()

    a = MyFun()
    a # randomnumber 1
    a # randomnumber 2
    ```
    但这和直接调 random 方法有什么区别啊。。。。
    cheetah
        11
    cheetah  
       2017-02-21 19:16:53 +08:00
    @Allianzcortex 最后两行应该是 `a()` 吧
    Herobs
        12
    Herobs  
       2017-02-21 19:18:59 +08:00
    obj.x 这种形式还可以用描述器,直接访问变量 x 这种形式应该是没有办法做到吧。
    eccstartup
        13
    eccstartup  
       2017-02-21 19:25:02 +08:00
    不懂,但是有点像 scheme 里 quote , eval 这些东西
    qsnow6
        14
    qsnow6  
    OP
       2017-02-21 19:34:03 +08:00
    @Allianzcortex
    是这样,这个类是一个库里随机生成 UserAgent 的方法 ;
    我有一个爬虫,代码里面的变量是写好的,比如 self.user_agent
    爬虫每次请求都会把 self.user_agent 作为自己的 useragent

    所以我就想直接让 self.user_agent 每次都引用 ua.random

    但是,发现是直接传的值过去,每次生成的内容是一样的。。
    qsnow6
        15
    qsnow6  
    OP
       2017-02-21 19:34:46 +08:00
    看了下原来的 ua.random 的实现就是通过 __getattr__ 来实现的
    qsnow6
        16
    qsnow6  
    OP
       2017-02-21 19:47:58 +08:00
    好了,再套一个类上去就搞定了


    class MyFun(object):

    def __repr__(self):

    from fake_useragent import UserAgent
    ua = UserAgent()
    return ua.random

    f = MyFun()
    binux
        17
    binux  
       2017-02-21 19:51:37 +08:00   ❤️ 1
    @qsnow6 #16 不不不,__repr__ 是搞笑的,要么改 self 对应类的 __get_attr__,要么用 __get__,具体见 https://docs.python.org/2/howto/descriptor.html
    binux
        18
    binux  
       2017-02-21 19:53:01 +08:00
    forrestchang
        19
    forrestchang  
       2017-02-21 20:16:04 +08:00
    看了一下,大致明白了 lz 的意思。

    你是要每次都 generate 一个新的 UserAgent ?

    直接定义一个 gen_ua() 不就好了,

    def gen_ua():
    return UserAgent().random

    然后

    self.user_agent = gen_ua()
    qsnow6
        20
    qsnow6  
    OP
       2017-02-21 20:23:27 +08:00
    @forrestchang 函数返回的是值,调用 self.user_agent 是不会变的,嘻嘻,刚开始我也没转过来
    forrestchang
        21
    forrestchang  
       2017-02-21 20:38:53 +08:00
    @qsnow6 那么这个样子呢,改成计算属性好了

    class WTF(object):
    def __init__(self):
    pass

    @property
    def user_agent(self):
    return UserAgent().random


    wtf = WTF()
    wtf.user_agent # call user_agent()

    __repr__ 不是像你这么用的

    Called by the repr() built-in function to compute the “ official ” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object.
    ericls
        22
    ericls  
       2017-02-21 21:06:44 +08:00 via iPhone
    Python 是按 assignment 传的
    junnplus
        23
    junnplus  
       2017-02-21 21:29:44 +08:00
    property 应该是正解吧
    Allianzcortex
        24
    Allianzcortex  
       2017-02-21 22:12:22 +08:00
    @cheetah Yep !!! a()!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2583 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 04:40 · PVG 12:40 · LAX 20:40 · JFK 23:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.