【问题标题】:python calling methods of class using different wayspython使用不同的方式调用类的方法
【发布时间】:2012-11-20 17:09:36
【问题描述】:

我有一些课:

class RSA:
 CONST_MOD=2
 def __init__(self):
  print "created"

 def fast_powering(self,number,power,mod):
  print "powering"

我想实例化它并调用fast_powering方法:

 def main():
  obj=RSA() # here instant of class is created 
  val=obj.fast_powering(10,2,obj.CONST_MOD)  #  and we call method of object
  print val

而且效果很好!

但我发现我也可以用一些不同的方式来做,比如:

def main():
 obj=RSA #do we create a link to the class without creating of object , or what?
 val=obj().fast_powering(10,2,obj().CONST_MOD) # and here we do something like
          # calling of static method of class in C++ without class instantiation,
          #  or ?
 print val

对不起,我觉得有点 C++ 的方式,但无论如何 令我惊讶的是,它也有效!
这里到底发生了什么?哪种方式更受欢迎?这对我来说有点神秘。

提前感谢您的任何回复!

【问题讨论】:

    标签: python oop class object


    【解决方案1】:

    在你的例子中,你正在做:

    obj = RSA
    

    这只是将名称 obj 绑定到绑定到 RSA 的任何内容,这是您实例中的类 RSA。然后你在做:

    obj().fast_powering(…)
    

    这相当于创建RSA的实例并在其上调用fast_powering方法。请注意,通过这种方式,您将在每次调用时获得RSA 的新实例,这可能不是您想要的。您还会注意到,__init__ 方法已在上面引用的行中调用。还要考虑:

    >>> class RSA:
    ...   def __init__(self):
    ...     print("foo")
    ... 
    >>> obj = RSA
    >>> obj() is obj()
    foo
    foo
    False
    

    这里我们看到语句obj() is obj() 实际上创建了两个对象,当然这两个对象并不相同。这与您的第一个示例相反,如下所示:

    >>> class RSA:
    ...   def __init__(self):
    ...     print("foo")
    ... 
    >>> obj = RSA()
    foo
    >>> obj is obj
    True
    

    【讨论】:

    • +1 为省略号使用正确的字形。开个玩笑,答案很好,但我希望看到更多。
    【解决方案2】:

    obj = RSA 之后,RSAobj 都指向同一个类 - 但是,您没有创建RSA 的实例。考虑一下:

    class Foo:
        def __init__(self):
            print 'Foo'
    
    Bar = Foo
    
    Foo()
    Bar()
    

    输出:

    富 富

    就哪种方式更可取而言:这实际上取决于您要做什么。但总的来说,第一种方法更可取,除非您有充分的理由使用第二种方法。

    【讨论】:

    • 那么,如果创建了这个链接 Bar= Foo,是否创建了类的实例?
    • @gekannt 不,Bar 只是定义为 Foo 类。注意当我们执行Bar = Foo 时不会调用init
    【解决方案3】:

    嗯...事实证明class RSA 也是一个实例,因此您可以将其存储在变量中(这是您的第二种方法正在做的事情),尽管我需要指出您实际上并没有做同样的事情他们俩的事情。当你这样做时:

    val=obj().fast_powering(10,2,obj().CONST_MOD)
    

    您实际上调用了 RSA 的构造函数两次(您有两个 obj() 调用),因此您会在控制台上看到两条“created”消息。

    在 Python 中有很多奇怪的方法可以做同样的事情。为了便于阅读,我更喜欢“常规”方式(在您的第一种方法中显示的方式),但这里有一个合法可行的快速示例:

    #!/usr/bin/env python
    
    class RSA(object):
        CONST_MOD=2
        def __init__(self):
            print "created"
    
        def fast_powering(self,number,power,mod):
            print "powering"
    
    def method1_good():
        obj=RSA() # here instant of class is created 
        val=obj.fast_powering(10,2,obj.CONST_MOD)  #  and we call method of object
        print val
    
    def method2_bad():
        obj=RSA #do we create a link to the class without creating of object , or what?
        val=obj().fast_powering(10,2,obj().CONST_MOD)
        print val
    
    def method3_badToo():
        getattr(RSA(), "fast_powering")(10,2,RSA().CONST_MOD)
    
    def method4_areYouNuts():
        for key, val in globals().iteritems():
            if isinstance(val, type) and (key == "RSA"):
                obj = val()
                getattr(obj, "fast_powering")(10,2,obj.CONST_MOD)
                break
    
    if __name__ == "__main__":
        print "Works with method1?"
        method1_good()
        print "Works with method2?"
        method2_bad()
        print "Works with method3?"
        method3_badToo()
        print "Works with method4?"
        method4_areYouNuts()
    

    也许这可能会给您一些需要寻找的东西,例如: Globals and Locals Gettattr 和 setattr(12

    如果您想深入挖掘...metaclasses 可以做的疯狂事情...(在我在 StackOverflow 中见过的最佳答案之一中进行了解释)

    【讨论】:

    • 我实际上没有看到第二个obj() 电话(你的第二段)。
    • 我从问题的第三个“代码块”中复制了它(第二个 main() 示例)
    • 哦,对了,我忽略了参数中的obj(),没关系。
    猜你喜欢
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    相关资源
    最近更新 更多