简体   繁体   中英

python calling methods of class using different ways

I have some class:

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

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

I want to instantiate it and call method 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

And it works fine!

But I found that I can do it a little bit different way too, like:

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

Sorry, I think a little bit in C++ way, but anyway to my great astonishment it works too!
What's actually happening here? Which wayn is more preffered? It's some misterious for me.

Thanks in advance for any replies!

In your example, you're doing:

obj = RSA

which is just binding the name obj to whatever was bound to RSA , which is the class RSA in your instance. Then you're doing:

obj().fast_powering(…)

Which is equivalent to creating an instance of RSA and calling the method fast_powering on it. Note that this way, you'll get a new instance of RSA on each call, which is probably not what you want. You'll also have noticed, that the __init__ method has been called in the line cited above. Also consider:

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

Here we see that the statement obj() is obj() in fact creates two objects, which are of course not identical. This is opposed to your first example, as demonstrated using:

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

After obj = RSA , both RSA and obj refer to the same class - you're not creating an instance of RSA , however. Consider this:

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

Bar = Foo

Foo()
Bar()

Output:

Foo
Foo

In terms of which way is more preferable: it really depends on what you are trying to do. But in general, the first method is preferable, unless you have a good reason to be using the second method.

Well... It turns out that class RSA is a instance too so you can store it in variables (which is what your second method is doing), although I need to point out you're not actually doing the same thing in both of them. When you do:

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

You are actually calling the RSA's constructor twice (you've got two obj() calls), and thus you'll see two " created " messages on the console.

There is a lot of weird ways of doing the same thing in Python. For readability sake, I prefer the "regular" way (the one shown on your first method),but here's a quick example of things that are legally doable:

#!/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()

Maybe this may give you some things to look for, such as: Globals and Locals Gettattr and setattr ( 1 and 2 )

And if you want to dig a bit more... the crazy things you can do with metaclasses ... (explained in one of the best answers I've ever seen in StackOverflow)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM