Class' instance as argument python - 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.

Related

Possible to force unique IDs to variables containing integers between -5 and 256 in python?

I have a class with several named attributes. I would like to be able to pass one of the classes attributes to itself and be able to determine specifically which attribute was passed.
Below is a trivial example of how I was doing it (using the "is" operator), until I discovered that special cached variable IDs are used for integer values between -5 and 256.
class AClass:
def __init__(self, one, two, three):
self.one = one
self.two = two
self.three = three
def getIndex(self, attribute):
if attribute is self.one:
return 1
elif attribute is self.two:
return 2
elif attribute is self.three:
return 3
def setByIndex(self, i, value):
if i == 1:
self.one = value
elif i == 2:
self.two = value
elif i == 3:
self.three = value
def setByAttrib(self, attribute, value):
i = self.getIndex(attribute)
self.setByIndex(i, value)
object = AClass(0, 0, 0)
object.setByAttrib(object.three, 10)
In the above example, the intention is to set object.three to 10. However, since all attributes are pointing to the cached location of integer 0, the getIndex function would evaluate true on any of them, and object.one (which appears first) will get set to 10. If the object was initialized with values 257, 257, 257, functionality would presumably be as intended.
So the question is, is there a way to either:
a) force the system to assign non-cached, unique memory locations for these attributes (even if they are set between -5 and 256), or
b) use some other method to check if an attribute passed as an argument is uniquely itself?
EDIT:
Since it was asked a couple times, one of the reasons I'm using this paradigm is due to the the lack of pointers in python. In the example above, the setByIndex function could be doing some complicated work on the attribute. Rather than write multiple identical functions for each variable (eg setOne, setTwo, setThree), I can write out a single generic function that is retrieving and setting by index (index is basically acting like a pointer). Yes, I could pass the attribute value as an argument and return the new set value and do the assignment in the scope where the specific attribute is known, but I am already returning a value. Yes, I could return a list, but it adds more complexity.
I do realize that there are better ways to implement what I need (eg key-value pairs for the attributes and index numbers) but it would be a lot of work to implement (thousands of changes). If there was a way to use the varaible ID as my unique identifier and continue to use the "is" operator (or similar), I wouldn't need to change too much. Not looking possible though. Appreciate the comments/responses.
I wouldn't worry about the memory locations, they are simply an implementation detail here. It's really about function design, so if you want to set object.three, then do exactly that, otherwise, you can create a mapping to an index if you wanted to:
class MyClass:
def __init__(self, *args):
self.one, self.two, self.three, *_ = args
# get an object by it's index
def get_by_index(self, index):
# here's how you could create such a mapping
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
return getattr(self, opts[index])
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# if you want to set by an index, then do that this way
def set_by_index(self, index, val):
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
setattr(self, opts[index], val)
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# otherwise, just set the attribute by the name
a = MyClass(0, 0, 0)
a.three = 55
The thing is, you're right, is will look at the three 0's the same way, because it never copied that data in the first place. one, two, three point to the same data because they were assigned the same data. Once you assign the attribute again, you've effectively re-binded that attribute to a new value, rather than updating an existing one.
Point being, don't worry about where the memory is for this implementation, just set explicitly against the attribute

Can I implement a function or better a decorator that makes func(a1)(a2)(a3)...(an) == func(a1, a2, a3,...,an)? [duplicate]

On Codewars.com I encountered the following task:
Create a function add that adds numbers together when called in succession. So add(1) should return 1, add(1)(2) should return 1+2, ...
While I'm familiar with the basics of Python, I've never encountered a function that is able to be called in such succession, i.e. a function f(x) that can be called as f(x)(y)(z).... Thus far, I'm not even sure how to interpret this notation.
As a mathematician, I'd suspect that f(x)(y) is a function that assigns to every x a function g_{x} and then returns g_{x}(y) and likewise for f(x)(y)(z).
Should this interpretation be correct, Python would allow me to dynamically create functions which seems very interesting to me. I've searched the web for the past hour, but wasn't able to find a lead in the right direction. Since I don't know how this programming concept is called, however, this may not be too surprising.
How do you call this concept and where can I read more about it?
I don't know whether this is function chaining as much as it's callable chaining, but, since functions are callables I guess there's no harm done. Either way, there's two ways I can think of doing this:
Sub-classing int and defining __call__:
The first way would be with a custom int subclass that defines __call__ which returns a new instance of itself with the updated value:
class CustomInt(int):
def __call__(self, v):
return CustomInt(self + v)
Function add can now be defined to return a CustomInt instance, which, as a callable that returns an updated value of itself, can be called in succession:
>>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44) # and so on..
50
In addition, as an int subclass, the returned value retains the __repr__ and __str__ behavior of ints. For more complex operations though, you should define other dunders appropriately.
As #Caridorc noted in a comment, add could also be simply written as:
add = CustomInt
Renaming the class to add instead of CustomInt also works similarly.
Define a closure, requires extra call to yield value:
The only other way I can think of involves a nested function that requires an extra empty argument call in order to return the result. I'm not using nonlocal and opt for attaching attributes to the function objects to make it portable between Pythons:
def add(v):
def _inner_adder(val=None):
"""
if val is None we return _inner_adder.v
else we increment and return ourselves
"""
if val is None:
return _inner_adder.v
_inner_adder.v += val
return _inner_adder
_inner_adder.v = v # save value
return _inner_adder
This continuously returns itself (_inner_adder) which, if a val is supplied, increments it (_inner_adder += val) and if not, returns the value as it is. Like I mentioned, it requires an extra () call in order to return the incremented value:
>>> add(1)(2)()
3
>>> add(1)(2)(3)() # and so on..
6
You can hate me, but here is a one-liner :)
add = lambda v: type("", (int,), {"__call__": lambda self, v: self.__class__(self + v)})(v)
Edit: Ok, how this works? The code is identical to answer of #Jim, but everything happens on a single line.
type can be used to construct new types: type(name, bases, dict) -> a new type. For name we provide empty string, as name is not really needed in this case. For bases (tuple) we provide an (int,), which is identical to inheriting int. dict are the class attributes, where we attach the __call__ lambda.
self.__class__(self + v) is identical to return CustomInt(self + v)
The new type is constructed and returned within the outer lambda.
If you want to define a function to be called multiple times, first you need to return a callable object each time (for example a function) otherwise you have to create your own object by defining a __call__ attribute, in order for it to be callable.
The next point is that you need to preserve all the arguments, which in this case means you might want to use Coroutines or a recursive function. But note that Coroutines are much more optimized/flexible than recursive functions, specially for such tasks.
Here is a sample function using Coroutines, that preserves the latest state of itself. Note that it can't be called multiple times since the return value is an integer which is not callable, but you might think about turning this into your expected object ;-).
def add():
current = yield
while True:
value = yield current
current = value + current
it = add()
next(it)
print(it.send(10))
print(it.send(2))
print(it.send(4))
10
12
16
Simply:
class add(int):
def __call__(self, n):
return add(self + n)
If you are willing to accept an additional () in order to retrieve the result you can use functools.partial:
from functools import partial
def add(*args, result=0):
return partial(add, result=sum(args)+result) if args else result
For example:
>>> add(1)
functools.partial(<function add at 0x7ffbcf3ff430>, result=1)
>>> add(1)(2)
functools.partial(<function add at 0x7ffbcf3ff430>, result=3)
>>> add(1)(2)()
3
This also allows specifying multiple numbers at once:
>>> add(1, 2, 3)(4, 5)(6)()
21
If you want to restrict it to a single number you can do the following:
def add(x=None, *, result=0):
return partial(add, result=x+result) if x is not None else result
If you want add(x)(y)(z) to readily return the result and be further callable then sub-classing int is the way to go.
The pythonic way to do this would be to use dynamic arguments:
def add(*args):
return sum(args)
This is not the answer you're looking for, and you may know this, but I thought I would give it anyway because if someone was wondering about doing this not out of curiosity but for work. They should probably have the "right thing to do" answer.

`__init__()` always raises error

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)

Is taking advantage of the one-time binding of function arguments a bad idea?

New python users often get tripped up by mutable argument defaults. What are the gotchas and other issues of using this 'feature' on purpose, for example, to get tweakable defaults at runtime that continue to display properly in function signatures via help()?
class MutableString (str):
def __init__ (self, value):
self.value = value
def __str__ (self):
return self.value
def __repr__ (self):
return "'" + self.value + "'"
defaultAnimal = MutableString('elephant')
def getAnimal (species=defaultAnimal):
'Return the given animal, or the mutable default.'
return species
And in use:
>>> help(getAnimal)
getAnimal(species='elephant')
Return the given animal, or the mutable default.
>>> print getAnimal()
elephant
>>> defaultAnimal.value = 'kangaroo'
>>> help(getAnimal)
getAnimal(species='kangaroo')
Return the given animal, or the mutable default.
>>> print getAnimal()
kangaroo
First, read Why are default values shared between objects. That doesn't answer your question, but it provides some background.
There are different valid uses for this feature, but they pretty much all share something in common: the default value is a transparent, simple, obviously-mutable, built-in type. Memoization caches, accumulators for recursive calls, optional output variables, etc. all look like this. So, experienced Python developers will usually spot one of these use cases—if they see memocache={} or accum=[], they'll know what to expect. But your code will not look like a use for mutable default values at all, which will be as misleading to experts as it is to novices.
Another problem is that your function looks like it's returning a string, but it's lying:
>>> print getAnimal()
kangaroo
>>> print getAnimal()[0]
e
Of course the problem here is that you've implemented MutableString wrong, not that it's impossible to implement… but still, this should show why trying to "trick" the interpreter and your users tends to open the door to unexpected bugs.
--
The obvious way to handle it is to store the changing default in a module, function, or (if it's a method) instance attribute, and use None as a default value. Or, if None is a valid value, use some other sentinel:
defaultAnimal = 'elephant'
def getAnimal (species=None):
if species is None:
return defaultAnimal
return species
Note that this is pretty much exactly what the FAQ suggests. Even if you inherently have a mutable value, you should do this dance to get around the problem. So you definitely shouldn't create a mutable value out of an inherently immutable one to create the problem.
Yes, this means that help(getAnimal) doesn't show the current default. But nobody will expect it to.
They will probably expect you to tell them that the default value is a hook, of course, but that's a job for a docstring:
defaultAnimal = 'elephant'
def getAnimal (species=None):
"""getAnimal([species]) -> species
If the optional species parameter is left off, a default animal will be
returned. Normally this is 'elephant', but this can be configured by setting
foo.defaultAnimal to another value.
"""
if species is None:
return defaultAnimal
return species
The only useful use I've seen for it is as a cache:
def fibo(n, cache={}):
if n < 2:
return 1
else:
if n in cache:
return cache[n]
else:
fibo_n = fibo(n-1) + fibo(n-2) # you can still hit maximum recursion depth
cache[n] = fibo_n
return fibo_n
...but then it's cleaner to use the #lru_cache decorator.
#lru_cache
def fibo(n):
if n < 2:
return 1
else:
return fibo(n-1) + fibo(n-2)

passing in self data in python

Can you please clarify how it is that self.add(x) below works the same way as self.data.append(x)?
That is, how does self.add(x) know to append to the list because we have not explicitly stated self.data.add(x)? When we state y.addtwice('cat'), 'cat' is added to 'self', not self.data.
class Bag:
def __init__(self):
self.data=[]
def add(self,x):
self.data.append(x)
return self.data
def addtwice(self,x):
self.add(x)
self.add(x)
return self.data
>>> y = Bag()
>>> y.add('dog')
['dog']
>>> y.addtwice('cat')
['dog', 'cat', 'cat']
Because addtwice calls methods which are defined on self, and because self.data is a "mutable type", addtwice's call to add will end up appending the value of self.data. add, in turn calls self.data.append
When calling a function in a computer program, you can think of the process as being a series of substitutions like this:
# -> means (substitution for)
# <= means "return"
y = Bag()
y.add('dog') ->
y.data.append(x) ->
#(machine code)
<= y.data
# at this point, at the command propmt, python will just print what was returned.
y.addtwice('cat')->
y.add('cat')->
y.data.append(x) ->
#(machine code)
<= y.data
#nothing cares about this return
y.add('cat')->
y.data.append(x) ->
#(machine code)
<= y.data
#nothing cares about this return either
<= y.data
# at this point, at the command propmt, python will just print what was returned.
self, itself, is never really appended in any of those cases though. self.data is.
self.add(x) calls the instance method add which in turn calls self.data.append(x)
When we state y.addtwice('cat'), 'cat' is added to 'self', not self.data
This is incorrect. cat is in fact added to self.data. Why would you think it was added to self?
y.add('dog') is the same as doing Bag.add(y, 'dog'). So add is really doing y.data.append('dog'), it's customary to use the name self instead.
y.addtwice('cat') is the same as doing Bag.addtwice(y, 'cat'). So addtwice is really doing y.add('cat') twice, which is the same as doing Bag.add(y, 'cat') twice. So addtwice is really doing y.data.append('cat') twice.
The self in each instance method is just an automatically added variable pointing to the instance it's called on, in this case y.
Let look at function add(self, x) from class Bag.
When that function is called, one of the parameter is self, which is the object itself, in this case, the same instance of Bag whose add function is called.
Therefore, in function add, calling self.data.append(x) is basically calling function append on data list of Bag, thus, adding the element x into the list.
Same thing for function addtwice. By calling function add twice, two elements are added into data list of Bag.
Both functions return the data list.
add(self, x) is just a function that you want to call.
append is a built in function that adds an element to the list.
so your add function basically uses append to add the element you want to the list and return the list you named data
self.addtwice will call self.add exactly two times and so will add the element twice.

Categories

Resources