`__init__()` always raises error - python

So, I have defined the following class which should resemble a probability mass function. However, its logic seems broken and it will raise SUM_ERROR every time I try to initialize a new object.
class ProbabilityMass(dict):
class InvalidEntries(Exception):
pass
SUM_ERROR = InvalidEntries("all values must add upto '1'")
VAL_ERROR = InvalidEntries("negative values are not allowed")
def __init__(self, pm):
dict.__init__(pm)
# Input requirements
if not self.sumsUptoOne():
raise ProbabilityMass.SUM_ERROR
if not self.isNonnegative():
raise ProbabilityMass.VAL_ERROR
def isNonnegative(self):
return all(d < 0 for d in self.values())
def sumsUptoOne(self):
return sum(self.values()) == 1
How can I fix this?

Calling dict.__init__() does not initialize the class. The correct call to super should look like this:
def __init__(self, pm):
super(ProbabilityMass, self).__init__(pm)
# Input requirements
...
As a side note, your isNonnegative() method is also incorrect. Change it to:
def isNonnegative(self):
return all(d >= 0 for d in self.values())

Usually, when dict.__init__() is called, it is because you used dict(). When a class is called like a function, an instance is created, and the instance's .__init__() method is called with the arguments given to the class. Well, calling an instance method is the same thing as calling the class method with the instance as a first argument. Therefore, x = dict() is short for:
x = new dict instance
dict.__init__(x)
If you already have an instance of dict (or a subclass) that was not initialized, you can call __init__() yourself. You must, however, remember to pass the instance as the first argument:
dict.__init__(self, pm)
The more common way is to use the built-in super():
super(ProbabilityMass, self).__init__(pm)

Related

Instance variable as function of other instance variables

Is it possible to define an instance variable in a class as a function of another? I haven't gotten it to work unless you redefine the "function instance variable" all the time.
Basically you could have a scenario where you have one instance variable that is a list of integers, and want to have the sum of these as an instance variable, that automatically redefines every time the list is updated.
Is this possible?
class Example:
list_variable = []
sum_variable = sum(list_variable)
def __init__(self, list_variable):
self.list_variable = list_variable
return
This will result in sum_variable = 0 unless you change it.
I understand that this is far from a major issue, you could either define sum_variable as a method or redefine it every time you change list_variable, I'm just wondering if it's possible to skip those things/steps.
Python offers the property decorator for a syntatically identical use of your example:
class Example:
list_variable = []
def __init__(self, list_variable):
self.list_variable = list_variable
return
#property
def sum_variable(self):
return sum(self.list_variable)
e = Example(list_variable=[10, 20, 30])
e.sum_variable # returns 60

Is there any difference between these two cases: passing class name vs object

I'm new to Python and not sure about many idioms. I have found code where a function gets a class name as argument. Is there any reason to do it? I've simplified the code to this:
class A:
def __init__(self):
print ("A")
def foo_1(a):
inst = a()
return inst
def foo_2(a):
inst = a
return inst
if __name__ == "__main__":
i1 = foo_1(A)
i2 = foo_2(A())
Is there any difference between implementing it like foo_1 ( the way it is implemented now), and the foo_2 (The way I would consider to be more intuitive)
Thanks!
These do slightly different things.
foo_1 gets passed a class (itself an object), not just its name. It then instantiates an instance of that class, which it returns.
foo_2 gets passed an instance (actually in this simplified example any object) and just returns it.
In this example this will mean that i1 and i2 seem to be the same. But they are actually different objects and will, for example, not compare equal.
You would use something like foo_1 as a factory of instances of some class or to modify the class object before creating an instance. And you would use foo_2 if you want to do something with an instance. In particular this means that if you call the function multiple times, you can pass the same instance every time, whereas foo_1 will always generate a new instance.
So, it depends on what you want to do.
What you have as foo_2 can be simplified as just using the object, which is what you should do.
Both options work, but foo_1 is an odd way of doing things unless you don't have immediate access to the class you want to instantiate.
i = foo_2(A())
is the same as
i = A()
Say you had a new class B, which had to be instantiated with some paramters. It's more complicated to call that from foo_1.
class B:
def __init__(self, c):
self.c = c
You can do:
i = B()
j = foo_2(B())
k = foo_1(B) => TypeError: __init__() missing 1 required positional argument: 'c'
You could modify foo_1 to take paramters though, and that could be useful, if you didn't know what class you might be instantiating (if you get the class via user input).
# function that takes 1 parameter followed by any number of paramters
def foo_3(klass, *params):
inst = klass(*params) # pass the any number of paramters onto the instantiation
return inst

Python: Getting value from calling function

In Python, is there a simple way for an invoked function to get a value from the calling function/class ? I'm not sure if I'm phrasing that right, but I'm trying to do something like this:
class MainSection(object):
def function(self):
self.var = 47 # arbitrary variable
self.secondaryObject = secondClass() # Create object of second class
self.secondaryObject.secondFunction(3) # call function in that object
and
class secondClass(object):
def secondFunction(self, input)
output = input + self.var # calculate value based on function parameter AND variable from calling function
return output
#Access self.var from MainSection
This might be my lack of knowledge about Python, but I'm having a hard time finding a clear answer here. Is the best way to do that just passing the variable I want in as another second parameter to the second class?
These are in separate files, if that makes a difference.
Is the best way to do that just passing the variable I want in as another second parameter to the second class?
Yes, especially if there's only a transient relationship between the objects:
class secondClass(object):
def secondFunction(self, input, var_from_caller)
output = input + var_from_caller # calculate value based on function parameter AND variable from calling function
return output
You can even pass around the whole object if you like:
class secondClass(object):
def secondFunction(self, input, calling_object)
output = input + calling_object.var # calculate value based on function parameter AND variable from calling function
return output
If the relationship is more permanent, you could consider storing references to the related objects in instance variables:
class MainSection(object):
def function(self):
self.var = 47 # arbitrary variable
self.secondaryObject = secondClass(self) # Create object of second class
self.secondaryObject.secondFunction(3) # call function in that object
...
class secondClass(object):
def __init__(self, my_friend):
self.related_object = my_friend
def secondFunction(self, input)
output = input + self.related_object.var # calculate value based on function parameter AND variable from calling function
return output
#Access self.var from MainSection

Class' instance as argument python

I am searching for a class method which decides which arguments will be given when an instance of the class is given as an argument.
I have this:
class Answers_Matrix(list):
def __setitem__(self, index, value):
if (type(value) is int):
if (0 <= value <= 255):
list.__setitem__(self, index, value)
else:
print "Invalid value size."
else:
print "Invalid value type. Value must be an integer."
def __repr__(self):
# a function I made which returns a matrix in a string format
return _matrix_to_string(self)
# **EDIT:**
# here I want a __asargument__ or something alike, so when an instance
# of this class is given as an argument I can decide what and how it
# will be given.
# Example:
# def __asargument__(self):
# array = (ctypes.c_ubyte*len(self))(*self)
# return array
Is there something alike in python which I can use?
What you want is not possible. There is no way to say that when you call
foo(Answers_Matrix())
foo will actually receive some other thing derived from Answers_Matrix(). This is for good reason, as it would be incredibly confusing and difficult to implement. Particularly, it's very likely that you'd want to use self as an argument to something in the hypothetical __asargument__ method, and that'd lead to either infinite recursion or extremely confusing context-sensitive semantics for when __asargument__ is or isn't called.
If you want object A to be replaced with object B whenever you try to use it for anything, don't have object A in the first place. Just use object B.

Reuse existing objects for immutable objects?

In Python, how is it possible to reuse existing equal immutable objects (like is done for str)? Can this be done just by defining a __hash__ method, or does it require more complicated measures?
If you want to create via the class constructor and have it return a previously created object then you will need to provide a __new__ method (because by the time you get to __init__ the object has already been created).
Here is a simple example - if the value used to initialise has been seen before then a previously created object is returned rather than a new one created:
class Cached(object):
"""Simple example of immutable object reuse."""
def __init__(self, i):
self.i = i
def __new__(cls, i, _cache={}):
try:
return _cache[i]
except KeyError:
# you must call __new__ on the base class
x = super(Cached, cls).__new__(cls)
x.__init__(i)
_cache[i] = x
return x
Note that for this example you can use anything to initialise as long as it's hashable. And just to show that objects really are being reused:
>>> a = Cached(100)
>>> b = Cached(200)
>>> c = Cached(100)
>>> a is b
False
>>> a is c
True
There are two 'software engineering' solutions to this that don't require any low-level knowledge of Python. They apply in the following scenarios:
First Scenario: Objects of your class are 'equal' if they are constructed with the same constructor parameters, and equality won't change over time after construction. Solution: Use a factory that hashses the constructor parameters:
class MyClass:
def __init__(self, someint, someotherint):
self.a = someint
self.b = someotherint
cachedict = { }
def construct_myobject(someint, someotherint):
if (someint, someotherint) not in cachedict:
cachedict[(someint, someotherint)] = MyClass(someint, someotherint)
return cachedict[(someint, someotherint)]
This approach essentially limits the instances of your class to one unique object per distinct input pair. There are obvious drawbacks as well: not all types are easily hashable and so on.
Second Scenario: Objects of your class are mutable and their 'equality' may change over time. Solution: define a class-level registry of equal instances:
class MyClass:
registry = { }
def __init__(self, someint, someotherint, third):
MyClass.registry[id(self)] = (someint, someotherint)
self.someint = someint
self.someotherint = someotherint
self.third = third
def __eq__(self, other):
return MyClass.registry[id(self)] == MyClass.registry[id(other)]
def update(self, someint, someotherint):
MyClass.registry[id(self)] = (someint, someotherint)
In this example, objects with the same someint, someotherint pair are equal, while the third parameter does not factor in. The trick is to keep the parameters in registry in sync. As an alternative to update, you could override getattr and setattr for your class instead; this would ensure that any assignment foo.someint = y would be kept synced with your class-level dictionary. See an example here.
I believe you would have to keep a dict {args: object} of instances already created, then override the class' __new__ method to check in that dictionary, and return the relevant object if it already existed. Note that I haven't implemented or tested this idea. Of course, strings are handled at the C level.

Categories

Resources