Python: how to define a class that behaves like a function? [duplicate] - python

This question already has answers here:
making a class callable in same instance
(2 answers)
Closed 1 year ago.
I would like to define in python a class that behaves like a function with additional attributes. In particular, it should be seamlessly applied to a variable.
Let’s try to explain with a mathematical example. Say I am very much into sinusoïdal functions, but also interested by their frequency. A function x -> sin(omega x) has the attribute frequency, namely the value of omega. It can also be applied to a float x.
I can write:
from numpy import sin, pi
class SinFunc:
def __init__(self, omega):
self.frequency = omega
def apply_to(self, x):
return sin(self.frequency * x)
I could then play with a sinusoïdal function:
MySinFunc = SinFunc(3)
print(MySinFunc.frequency)
print(MySinFunc.apply_to(pi))
# output
# 3
# 0 (almost!)
But what I would like is to be able to write directly MySinFunc(pi), with the attribute frequency still defined.
How to achieve that?
Thanks!

To make an object callable, you need to add a __call__ class method that will handle the call.
Rename your apply_to function to __call__ and it will work.

Related

Using constructor parameter variable names during object instantiation in Python?

When declaring a new instance of an object in python, why would someone use the names of the variables from the parameters at instatntiation time? Say you have the following object:
class Thing:
def __init__(self,var1=None,var2=None):
self.var1=var1
self.var2=var2
The programmer from here decides to create an instance of this object at some point later and enters it in the following way:
NewObj = Thing(var1=newVar,var2=otherVar)
Is there a reason why someone would enter it that way vs. just entering the newVar/otherVar variables into the constructor parameters without using "var1=" and "var2="? Like below:
NewObj = Thing(newVar,otherVar)
I'm fairly novice at using python, and I couldn't find anything about this specific sort of syntax even if it seems like a fairly simple/straightforward question
The reason is clarity, not for the computer, but for yourself and other humans.
class Calculation:
def __init__(self, low=None, high=None, mean=None):
self.low=low
self.high=high
self.mean=mean
...
# with naming (notice how ordering is not important)
calc = Calculation(mean=0.5, low=0, high=1)
# without naming (now order is important and it is less clear what the numbers are used for)
calc = Calculation(0, 1, 0.5)
Note that the same can be done for any function, not only when initializing an object.

Most pythonic way to specify which object function to use in a function [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 3 years ago.
I am setting a function where the user can specify how to initialize a variable. Here is a minimal example
def setValue( typeOf ):
if typeOf == 'normal':
a = np.random.normal( parameters)
if typeOf == 'uniform':
a = np.random.uniform(parameters)
However, in my real case, there are dozens of initialization options. I am wondering if I can make the code more elegant my specifying directly how the user wants to initialize the variable
def setValue( something ):
something hapenng
a = np.random.whatever_user_specified
It is not a question of being pythonic or not, but is rather a question of code design. There are multiple ways to achieve what you want, and your choice mainly depends on the function contract. That said, one approach would be to accept the initializing function as the argument:
def setValue(distribution):
a = distribution(parameters)
setValue(np.random.normal)
with the use of functools.partial you can fixate parameters of the initializer if necessary
setValue(partial(np.random.normal, scale=1))
A different approach would be to have a static mapping between names and
initializers:
distribution = {
'uniform': np.random.uniform,
'normal': np.random.normal,
}
def setValue(name):
a = distribution[name](parameters)
setValue('normal')
Finally, you can always use introspection to call the method indirectly
def setValue(name):
a = getattr(np.random, name)(parameters)
setValue('uniform')
but this is a subject to code smell and also is not secure if being run in an untrusted environment.
There are other approaches as well, but they are far more complicated and, as I said, mainly depend on the code design.
Use getattr to fetch a function by name:
method = "uniform"
if method in ["normal", "uniform"]:
func = getattr(np.random, method)
func()
# => 0.10683518702441452
You could also be excepting AttributeError, but that might give a bit more access than you meant to give.
Maybe you want to use getattr()?
def setValue(typeOf):
func = getattr(np.random, typeOf)
a = func(parameters)

Python Class shows name not defined [duplicate]

This question already has answers here:
Python - Why is this class variable not defined in the method?
(3 answers)
Why is instance variable not getting recognized
(2 answers)
Closed 6 years ago.
I am writing a piece of code for a homework class, which should allow me to calculate various distance statistics about two lists. However, when I assign the lists to the class, and try to print the result of one of the functions, I get the error,
NameError: name 'ratings1' is not defined
Leading me to believe that I did something incorrectly either in my __init__ function or the referencing in the functions. Can you help clarify what I'm doing wrong?
class similarity:
def __init__(self, ratingX, ratingY):
self.ratings1=ratingX
self.ratings2=ratingY
def minkowski(self,r):
self.r=r
mink=0
length=len(ratings1)
for i in range(0,length):
mink=mink+(abs(ratings1[i]-ratings2[i]))**r
mink=mink**(1/r)
result='Given r=%d, Minkowski distance=%f'%(r,mink)
return result
def pearson(self):
Xavg=average(ratings1)
Yavg=average(ratings2)
n=len(ratings1)
diffX=[]
diffY=[]
for i in range(0,n):
diffX.append(ratings1[i]-Xavg)
diffY.append(ratings2[i]-Yavg)
return diffX
diffXY=[]
for i in range(0,n):
diffXY.append(diffX[i]*diffY[i])
example2=similarity([1,3,5,5,6],[4,6,10,12,13])
print(example2.pearson())
Note: this error persists if I change the references to "ratings1/2" to "ratingsX/Y" in the functions.
You need to use self before every reference to instance variable, ie self.ratings1, and your indentation is wrong as well.
ratings are associated with class. Use self.ratings1 and so on..
I just figured out my mistake. For each function I failed to use the self. phrase before the ratings name. To amend this, I added
ratings1=self.
ratings2=self.ratings2
To the beginning of each function. Problem solved.

Python: Using eval() in class / different methods of case distinction [duplicate]

This question already has answers here:
Access to class attributes by using a variable in Python? [duplicate]
(2 answers)
Closed 7 years ago.
I got a class:
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(self.eval(character+"Thing"))
(Important is the last line)
The test script would look like this:
x = thing(1, 2)
x.test("b")
Trying to run this it screams at me:
AttributeError: 'thing' object has no attribute 'eval'
Makes sense, so I tried this:
print(self.(eval(character+"Thing")))
Now its a Syntax error: .(
So is there a way Í could do this? And if not, is there a way to do this kind of case distinction without having to list all possible cases? (like using if-statements or the switch equivalent)
Oh, and I know that in this case I could just use a dictionary instead of a class, but that is not what I am searching for...
Your question is very broad and you're probably better off watching a talk on polymorphism and the super function(behaviour distinction without if) or python design patterns.
For the specific problem you posted you want to use getattr:
getattr(object, name[, default])
Return the value of the named
attribute of object. name must be a string. If the string is the name
of one of the object’s attributes, the result is the value of that
attribute. For example, getattr(x, 'foobar') is equivalent to
x.foobar. If the named attribute does not exist, default is returned
if provided, otherwise AttributeError is raised.
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(getattr(self,character+"Thing"))
Example Demo
>>> t = thing(1, 2)
>>> t.test("a")
1

How to pprint and automatically include the the variable name [duplicate]

This question already has answers here:
How to print original variable's name in Python after it was returned from a function?
(13 answers)
Simpler way to create dictionary of separate variables?
(27 answers)
Closed 8 years ago.
For Python 2.7 I have a little utility for debugging:
def printvar(label, var):
print "%s:\n%s" % (label, pformat(var))
Often I call it like printvar("foo", foo).
Is it possible to simplify that a tiny bit and only pass in the variable, like printvar(foo), but still have it print the name of the variable? Using introspection or something?
You can't do that, but you can approximate the reverse: pass in only the label, and have it grab the actual value. Here's a quick version:
def printvar(label):
for frame in inspect.getouterframes(inspect.currentframe())[1:]:
local_vars = frame[0].f_locals
if label in local_vars:
print "%s:\n%s" % (label, frame[0].f_locals[label])
return
raise NameError("No such variable")
Then you can do this:
def foo():
x = 2
printvar('x')
>>> foo()
x:
2
This is, of course, very hacky business: the code looks through the local-variable namespaces of every stack frame in its call chain. Normally this kind of trickery is to be avoided, but for debugging purposes it can be useful in a pinch.

Categories

Resources