This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 7 years ago.
I'm trying to assign class methods to class attribute, so I can call the methods from string. When using the class I want to call it from string like:
A.MAP['add'](x, y)
A.MAP['subtract'](x, y)
This is my current code:
class A:
MAP = {
'add' : A.add(x, y),
'subtract' : A.subtract(x, y),
}
#classmethod
def add(cls, x, y)
return x + y
#classmethod
def subtract(cls, x, y)
return x - y
However the result shown error that A is not defined at the line of assigning A.add to MAP['add']. For short functions I can use lambda. However, in case of a longer function, how can I achieve this design?
Note that when you try:
class A:
MAP = {
'add' : A.add(x, y),
'subtract' : A.subtract(x, y),
}
you are trying to access e.g. A.add before the name A exists (the class isn't bound to the name until definition completes) and before the name add exists (you haven't defined that method yet). Everything at the top level of the class definition is done in order.
You need to put the class methods into the dictionary after the class has been defined (they don't become callable until definition is complete):
class A:
MAP = {}
#classmethod
def add(cls, x, y): # note colon
return x + y
#classmethod
def subtract(cls, x, y): # also here
return x - y
A.MAP['add'] = A.add
A.MAP['subtract'] = A.subtract
Note that, as neither class method uses cls, you could make them #staticmethods instead. Or just use functions - Python isn't Java, you don't need to put everything into a class.
Alternatively, you can use getattr to access attributes (including class methods) by name:
>>> class A:
#classmethod
def add(cls, x, y):
return x + y
#classmethod
def subtract(cls, x, y):
return x - y
>>> getattr(A, 'add')(1, 2)
3
Please do not program in python like that, instead use a more standard oop approach like this:
#!/usr/bin/env python
class A:
def __init__(self):
pass
#classmethod
def add(self, x, y):
return x + y
#classmethod
def subtract(self, x, y):
return x - y
if __name__ == "__main__":
a = A()
print a.add(1,2) # ans: 3
print a.subtract(2,1) # ans: 1
Related
For a long time I have been puzzled by Alex Martelli's remark about:
(...) the fuzzy unattainable goal of making repr's returned value
acceptable as input to eval!
So I gave it a try and came up with this:
class Sic():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
self.method_var = lambda x, y, z : x + y + z
def __repr__(self):
def right_quotes(value):
return repr(value).translate(str.maketrans('\'\"', '\"\''))
from inspect import signature
class_sig = signature(self.__class__)
fields = tuple('{}={}'.format(k,right_quotes(v)) for k,v in self.__dict__.items() if k in class_sig.parameters)
return self.__class__.__name__ + str(tuple(sorted(fields))).replace("\'","")
Is this a correct general implementation of __repr__? If not could you give an example where it fails?
(I have improved the original version with the suggestion of Barmar, and responding to the objection of Kuco 23. I am looking here to a most general solution, even if it involves using introspection.)
What the quote means is that, when a string returned from the __repr__ method is ran on a python interpreter, it should evaluate to the object at its initialization stage.
The code you provided has a couple of faults.
Any object encoded in the __repr__ return string, should also be represented with their __repr__ method.
And also the self.__dict__.items() will return (name, value) pair for every attribute name set to the object self. The problem here is that some of those object were not used for the self's initialization. For example if your code was modified as
class Sic():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
self.method_var = someFunction(x, y, z)
def __repr__(self):
fields = tuple("{}={}".format(k, v) for k, v in self.__dict__.items())
return self.__class__.__name__ + str(tuple(sorted(fields))).replace("\'","")
the repr method would return Sic(x=x0, y=y0, z=z0, method_var=mv0), even though that string's evaluation would be invalid, as the __init__ method only takes 3 arguments.
The safest option would be to implement the __repr__ method for any class you implement separately, as in
class Sic():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
args = map(repr, (self.x, self.y, self.z))
return f"Sic({', '.join(args)})"
If you insist on defining a __repr__ method for a custom class, you would have to know for each object, which arguments the __init__ method takes in, which would probably require some additional modifications to every class and make the code more complex.
I want to get class instance into function as argument, like code below. I know it doesn`t work.
class coordinate:
x = 1
y = 2
inst = coordinate()
def get_class(instance):
return instance.x + instance.y
get_class(inst)
Just getting instance`s inner variable is one of the solution, but the class that I want to use contains pretty diverse things. It makes code confusing
x = inst.x
y = inst.y
def get_class(x, y):
return x + y
get_class(x, y)
Is there any possible way?
First, let me point out that you probably want your x and y to be instance attributes and not class attributes.
Then if you want a function that takes a class instance as argument, what you want is probably an instance method.
class Coordinates:
def __init__(self, x, y):
self.x = x
self.y = y
def sum_coordinates(self):
return self.x + self.y
Coordinates(1, 2).sum_coordinates() # 3
This question already has answers here:
Functions, Callable Objects, and how both are created in Python
(2 answers)
Closed 5 years ago.
class Adder:
def __call__(self, x, y):
return x + y
add1 = Adder()
def add2(x, y):
return x + y
What's the difference between add1 and add2 other than the type?
In your super-simple example. there's no practical difference, since functions are also callable objects.
However, a callable object is an object of a class that you write, so you may write this code:
class Counter:
def __init__(self, value = 0):
self.n = 0
def __call__(self):
self.n += 1
return self.n
def __repr__(self):
return str(self.n)
redWins = Counter()
blueWins = Counter()
if foo():
redWins()
else:
blueWins()
print("Red has won {} times.\nBlue has won {} times."
.format(redWins, blueWins))
And you'll find it hard to implement such a class using only functions. Even if you try to do it with global variables, you can't have separate instances of one single global variable.
See more: Functions, Callable Objects, and how both are created in Python
In your example, there's no functional difference but since add1 is an object, you can store information in the members:
class Adder:
def __init__(self):
self.__memory = 0
def __call__(self, x, y):
self.__memory += x
return x+y+self.__memory
add1 = Adder()
print(add1(10,10))
print(add1(10,10))
you get 30 then 40. You can do that with a function, but then you need a global variable, and using global variables is really asking for trouble.
I get a
TypeError: unbound method mult() must be called with calculadora instance as first argument (got int instance instead)
when running my python file :
from __future__ import print_function
class calculadora:
def suma(x,y):
added = x + y
print(added)
def resta(x,y):
sub = x - y
print(sub)
def mult(x,y):
multi = x * y
print(multi)
calculadora.mult(3,5)
If you want to access methods as static methods(accesing methods without the clas instance), you need to decorate them with #staticmethod:
class calculadora:
#staticmethod
def suma(x, y):
added = x + y
print(added)
#staticmethod
def resta(x, y):
sub = x - y
print(sub)
#staticmethod
def mult(x, y):
multi = x * y
print(multi)
If you meant instance methods, you need to create instance first. and need to modify methods' signatures to include self as the first parameter:
class calculadora:
def suma(self, x, y): # not `self`, refering class instance
added = x + y
print(added)
def resta(self, x, y):
sub = x - y
print(sub)
def mult(self, x, y):
multi = x * y
print(multi)
c = calculadora() # Create instance
c.mult(3,5) # Access the method through instance, (not class)
I have a class MyClass:
class MyClass(object):
def __init__(self):
pass
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
The class borrows from Origin:
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
How can I copy the docstring from Origin.func to MyClass.my_function automatically so that Sphinx Autodoc recognises it? And how can I extend the original docstring by a couple of words?
Edit:
Afaik, I cannot just change __doc__ after the definition of the function since Sphinx would not find it then. Or if it did, where would the "docfix" go?
I'm not clear on exactly how Sphinx works, but assuming it reads from __doc__ rather than parsing the source, there are a number of options.
Consider the simpler example...
def add(x, y):
return x + y
...which is virtually identical to...
add = lambda x, y: x + y
In either case, you cannot refer to the symbol add inside its definition, since the symbol is not defined at that point. Nor can you refer to the function object which the symbol add will ultimately refer to, since it hasn't been created yet.
Therefore, you can only modify add.__doc__ after the symbol has been defined...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
...but this may be a little more verbose than we'd like.
Another option is to exploit the fact that the Python decorator syntax...
#my_decorator
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = my_decorator(add)
...that is, although it's placed before the function definition, it's executed after the function is defined, so you can reference the function object inside the body of the decorator function.
A decorator function is required to return a callable object, but given that we have no need to change the behavior of the add function, we can just return the argument which is passed in to the decorator, so given the decorator function...
def set_fixed_docstring(func):
func.__doc___ = 'This is my docstring'
return func
...used like...
#set_fixed_docstring
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_fixed_docstring(add)
...or...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Obviously, a fixed docstring isn't much use here, so we need to parameterize the decorator, which is a little more complex.
In this instance, we need our decorator function to be callable with a string parameter, and to return a callable object which takes the target function as a parameter.
The most common way to do this is to define another function within the decorator function, such that the inner function can refer to symbols defined in the outer function. So the function...
def set_docstring_to(docstring):
def wrapper(func):
func.__doc___ = docstring
return func
return wrapper
...used like...
#set_docstring_to('This is my docstring')
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_docstring_to('This is my docstring')(add)
...which boils down to the same code as before...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Putting all this together, if you were to use a decorator like...
def copy_docstring_from(source):
def wrapper(func):
func.__doc__ = source.__doc__
return func
return wrapper
...then you can just do...
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
class MyClass(object):
def __init__(self):
pass
#copy_docstring_from(Origin.func)
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
...which should achieve the desired result with the minimum amount of code.