Can't add variable to an instance of List - python-3.x

I'd like to add a variable called foo to the weights of a Conv2D layer to keep track of some book keeping.
This is my attempt:
kernels = model.get_layer(name='conv2d_1').get_weights()
kernels.foobar = 4
Note that kernels is of type list.
However, the previous code produce the following error:
AttributeError: 'list' object has no attribute 'foobar'
Any idea?

You can't use kernels.__setattr__('foobar', 4) / setattr(kernels, 'foobar', 4) in the way that you want, so you can't set an arbitrary attribute like you can with a custom class.
Perhaps in this case you do a very basic subclass on list:
class Kernels(list):
def __setattr__(self, attr, x):
# Make sure you aren't overriding some method of lists,
# such as `.append()`
if attr in self.__dir__():
raise ValueError('%s is already a method.')
super().__setattr__(attr, x)
>>> k = Kernels([1, 2, 3])
>>> k.foobar = 4
>>> k
[1, 2, 3]
>>> k.foobar
4

Related

Can I use side_effect in my mocking to provide an indefinite number of values?

So I can use an iterable with side_effect in python mock to produce changing values returned by my calls to the mock:
some_mock.side_effect = [1, 2, 3]
return_value provides the same value every time
some_mock.return_value = 8
Is there a way I can use one or both of these methods so that a mock produces some scheduled values to begin and then an infinite response of one particular value when the first set is exhausted? i.e.:
[1, 2, 3, 8, 8, 8, 8, 8, 8, etc. etc etc.]
There is no specific build-in feature that does that, but you can achieve this by adding a side effect that does this.
In the cases I can think of, it would be sufficient to just add some highest needed number of values instead of an infinite number, and use the side_effect version that takes a list:
side_effect = [1, 2, 3] + [8] * 100
my_mock.side_effect = side_effect
If you really need that infinite number of responses, you can use the other version of side_effect instead that uses a function object instead of a list. You need some generator function that creates your infinite list, and iterate over that in your function, remembering the current position. Here is an example implementation for that (using a class to avoid global variables):
from itertools import repeat
class SideEffect:
def __init__(self):
self.it = self.generator() # holds the current iterator
#staticmethod
def generator():
yield from range(1, 4) # yields 1, 2, 3
yield from repeat(8) # yields 8 infinitely
def side_effect(self, *args, **kwargs):
return next(self.it)
...
my_mock.side_effect = SideEffect().side_effect
This should have the wanted effect.

How can I make an Enum that allows reused keys? [duplicate]

I'm trying to get the name of a enum given one of its multiple values:
class DType(Enum):
float32 = ["f", 8]
double64 = ["d", 9]
when I try to get one value giving the name it works:
print DType["float32"].value[1] # prints 8
print DType["float32"].value[0] # prints f
but when I try to get the name out of a given value only errors will come:
print DataType(8).name
print DataType("f").name
raise ValueError("%s is not a valid %s" % (value, cls.name))
ValueError: 8 is not a valid DataType
ValueError: f is not a valid DataType
Is there a way to make this? Or am I using the wrong data structure?
The easiest way is to use the aenum library1, which would look like this:
from aenum import MultiValueEnum
class DType(MultiValueEnum):
float32 = "f", 8
double64 = "d", 9
and in use:
>>> DType("f")
<DType.float32: 'f'>
>>> DType(9)
<DType.double64: 'd'>
As you can see, the first value listed is the canonical value, and shows up in the repr().
If you want all the possible values to show up, or need to use the stdlib Enum (Python 3.4+), then the answer found here is the basis of what you want (and will also work with aenum):
class DType(Enum):
float32 = "f", 8
double64 = "d", 9
def __new__(cls, *values):
obj = object.__new__(cls)
# first value is canonical value
obj._value_ = values[0]
for other_value in values[1:]:
cls._value2member_map_[other_value] = obj
obj._all_values = values
return obj
def __repr__(self):
return '<%s.%s: %s>' % (
self.__class__.__name__,
self._name_,
', '.join([repr(v) for v in self._all_values]),
)
and in use:
>>> DType("f")
<DType.float32: 'f', 8>
>>> Dtype(9)
<DType.float32: 'd', 9>
1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Getting the name of the class of the tabs of a Tkinter notebook [duplicate]

How do I find out the name of the class used to create an instance of an object in Python?
I'm not sure if I should use the inspect module or parse the __class__ attribute.
Have you tried the __name__ attribute of the class? ie type(x).__name__ will give you the name of the class, which I think is what you want.
>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'
If you're still using Python 2, note that the above method works with new-style classes only (in Python 3+ all classes are "new-style" classes). Your code might use some old-style classes. The following works for both:
x.__class__.__name__
Do you want the name of the class as a string?
instance.__class__.__name__
type() ?
>>> class A:
... def whoami(self):
... print(type(self).__name__)
...
>>>
>>> class B(A):
... pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
class A:
pass
a = A()
str(a.__class__)
The sample code above (when input in the interactive interpreter) will produce '__main__.A' as opposed to 'A' which is produced if the __name__ attribute is invoked. By simply passing the result of A.__class__ to the str constructor the parsing is handled for you. However, you could also use the following code if you want something more explicit.
"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)
This behavior can be preferable if you have classes with the same name defined in separate modules.
The sample code provided above was tested in Python 2.7.5.
In Python 2,
type(instance).__name__ != instance.__class__.__name__
# if class A is defined like
class A():
...
type(instance) == instance.__class__
# if class A is defined like
class A(object):
...
Example:
>>> class aclass(object):
... pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>
>>> class bclass():
... pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>
Alternatively you can use the classmethod decorator:
class A:
#classmethod
def get_classname(cls):
return cls.__name__
def use_classname(self):
return self.get_classname()
Usage:
>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'
Good question.
Here's a simple example based on GHZ's which might help someone:
>>> class person(object):
def init(self,name):
self.name=name
def info(self)
print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person
Apart from grabbing the special __name__ attribute, you might find yourself in need of the qualified name for a given class/function. This is done by grabbing the types __qualname__.
In most cases, these will be exactly the same, but, when dealing with nested classes/methods these differ in the output you get. For example:
class Spam:
def meth(self):
pass
class Bar:
pass
>>> s = Spam()
>>> type(s).__name__
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__ # type not needed here
'Bar'
>>> type(s).Bar.__qualname__ # type not needed here
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'
Since introspection is what you're after, this is always you might want to consider.
You can simply use __qualname__ which stands for qualified name of a function or class
Example:
>>> class C:
... class D:
... def meth(self):
... pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'
documentation link qualname
To get instance classname:
type(instance).__name__
or
instance.__class__.__name__
both are the same
You can first use type and then str to extract class name from it.
class foo:pass;
bar:foo=foo();
print(str(type(bar))[8:-2][len(str(type(bar).__module__))+1:]);
Result
foo
If you're looking to solve this for a list (or iterable collection) of objects, here's how I would solve:
from operator import attrgetter
# Will use a few data types to show a point
my_list = [1, "2", 3.0, [4], object(), type, None]
# I specifically want to create a generator
my_class_names = list(map(attrgetter("__name__"), map(type, my_list))))
# Result:
['int', 'str', 'float', 'list', 'object', 'type', 'NoneType']
# Alternatively, use a lambda
my_class_names = list(map(lambda x: type(x).__name__, my_list))

When the Python __call__ method gets extra first argument?

The following sample
import types
import pprint
class A:
def __call__(self, *args):
pprint.pprint('[A.__call__] self=%r, args=%r'
% (self, list(args)))
class B:
pass
if __name__ == '__main__':
a = A()
print(callable(a))
a(1, 2)
b = B()
b.meth = types.MethodType(a, b)
b.meth(3, 4)
prints
True
'[A.__call__] self=<__main__.A object at 0xb7233c2c>, args=[1, 2]'
('[A.__call__] self=<__main__.A object at 0xb7233c2c>, args=[<__main__.B '
'object at 0xb71687cc>, 3, 4]')
The number of the __call__ method arguments is changed in the
b.meth(3, 4) example. Please explain the first one (__main__.B
object...) and when Python does provide it?
Using Python 3.5.3 on Debian 9.9 Stretch
The important concept here is that a class function is a function that has 'self' bound to it as its first argument.
I'll demonstrate in a couple of examples. The following code will be identical for all examples:
import types
# Class with function
class A:
def func(*args):
print('A.func(%s)'%(', '.join([str(arg) for arg in args])))
# Callable function-style class
class A_callable:
def __call__(*args):
print('A_callable.__call__(%s)'%(', '.join([str(arg) for arg in args])))
# Empty class
class B():
pass
# Function without class
def func(*args):
print('func(%s)'%(', '.join([str(arg) for arg in args])))
Now let's consider a couple of examples:
>>> func(42)
func(42)
This one is obvious. It just calls the function func with argument 42.
The next ones are more interesting:
>>> A().func(42)
A.func(<__main__.A object at 0x7f1ed9ed2908>, 42)
>>> A_callable()(42)
A_callable.__call__(<__main__.A_callable object at 0x7f1ed9ed28d0>, 42)
You can see that the class object self is automatically given to the function as the first argument. It is important to note that the self argument is not added because the function is stored in an object, but because the function was constructed as part of the object, and therefore has the object bound to it.
To demonstrate:
>>> tmp = A().func
>>> tmp
<bound method A.func of <__main__.A object at 0x7f1ed9ed2978>>
>>> tmp(42)
A.func(<__main__.A object at 0x7f1ed9ed2978>, 42)
>>> tmp = A_callable().__call__
>>> tmp
<bound method A_callable.__call__ of <__main__.A_callable object at 0x7f1ed9ed2908>>
>>> tmp(42)
A_callable.__call__(<__main__.A_callable object at 0x7f1ed9ed2908>, 42)
The self argument does not get added because you write a. before it. It is part of the function object itself, storing it in a variable still keeps that binding.
You can also manually bind a class object to a function, like this:
>>> tmp = types.MethodType(func, B)
>>> tmp
<bound method func of <class '__main__.B'>>
>>> tmp(42)
func(<class '__main__.B'>, 42)
On the other hand, just assigning a function to a class does not bind self to the function. As previously mentioned, the argument does not get dynamically added when called, but statically when constructed:
>>> b = B()
>>> b.func = func
>>> b.func
<function func at 0x7f1edb58fe18>
>>> b.func(42)
func(42) # does NOT contain the `self` argument
That is why we need to explicitely bind self to the function if we want to add it to an object:
>>> b = B()
>>> b.func = types.MethodType(func, b)
>>> b.func
<bound method func of <__main__.B object at 0x7f1ed9ed2908>>
>>> b.func(42)
func(<__main__.B object at 0x7f1ed9ed2908>, 42)
The only thing left is to understand how binding works. If a method func has a parameter a bound to it, and gets called with *args, it will add a to the beginning of *args and then pass it to the function. The beginning is important here.
Now we know everything needed to understand your code:
>>> a = A_callable()
>>> b = B()
>>> b.func = types.MethodType(a, b)
>>> b.func
<bound method ? of <__main__.B object at 0x7f1ed97e9fd0>>
>>> b.func(42)
A_callable.__call__(<__main__.A_callable object at 0x7f1ed97fb2b0>, <__main__.B object at 0x7f1ed97e9fd0>, 42)
First of all, we can change the b.func to plain tmp because, as previously discussed, adding a function to an object does not change its type or functionality. Only binding self does.
Then, let's step through the code piece by piece:
>>> a = A_callable()
>>> b = B()
So far so good. We have an empty object b and a callable object a.
>>> tmp = types.MethodType(a,b)
This line is the crux. If you understand this, you will understand everything.
tmp is now the function a with b bound to it. That means, if we call tmp(42), it adds b to the beginning of its arguments. a will therefore receive b, 42. Then, because a is callable, it forwards its arguments to a.__call__.
That means, we are at the point where tmp(42) is equal to a.__call__(b, 42).
Because __call__ is a class function of A_callable, a is automatically bound to the __call__ function during the construction of a. Therefore before the arguments reach A_callable.__call__, a gets added to the beginning of the argument list, meaning the arguments are now a, b, 42.
Now we are at the point where tmp(42) equals A_callable.__call__(a, b, 42). This is exactly what you see:
>>> tmp = types.MethodType(a, b)
>>> tmp(42)
A_callable.__call__(<__main__.A_callable object at 0x7f1ed97fb2b0>, <__main__.B object at 0x7f1ed97e9fd0>, 42)
>>> A_callable.__call__(a, b, 42)
A_callable.__call__(<__main__.A_callable object at 0x7f1ed97fb2b0>, <__main__.B object at 0x7f1ed97e9fd0>, 42)
Now if you split your arguments into self, *args, you basically just take away the first argument and store it in self. Your first argument is a, so self will be a, and your other *args will be b, 42. Again, this is exactly what you see.

Is it possible to adapt this approach of using dictionaries to find/evaluate one of many functions and its corresponding args?

Suppose one has several separate functions to evaluate some given data. Rather than use redundant if/else loops, one decides to use a dictionary key to find the particular function and its corresponding args. I feel like this is possible, but I can't figure out how to make this work. As a simplified example (that I hope to adapt for my case), consider the code below:
def func_one(x, a, b, c=0):
""" arbitrary function """
# c is initialized since it is necessary in func_two and has no effect in func_one
return a*x + b
def func_two(x, a, b, c):
""" arbitrary function """
return a*x**2 + b*x + c
def pick_function(key, x=5):
""" picks and evaluates arbitrary function by key """
if key != (1 or 2):
raise ValueError("key = 1 or 2")
## args = a, b, c
args_one = (1, 2, 3)
args_two = (4, 5, 3)
## function dictionary
func_dict = dict(zip([1, 2], [func_one, func_two]))
## args dictionary
args_dict = dict(zip([1, 2], [args_one, args_two]))
## apply function to args
func = func_dict[key]
args = args_dict[key]
## my original attempt >> return func(x, args)
return func(x, *args) ## << EDITED SOLUTION VIA COMMENTS BELOW
print(func_one(x=5, a=1, b=2, c=3)) # prints 7
But,
print(pick_function(1))
returns an error message
File "stack_overflow_example_question.py", line 17, in pick_function
return func(x, args)
TypeError: func_one() missing 1 required positional argument: 'b'
Clearly, not all of the args are being passed through with the dictionary. I've tried various combinations of adding/removing extra brackets and paranthesis from args_one and args_two (as defined in pick_function). Is this approach fruitful? Are there other convenient (in terms of readability and speed) approaches that do not require many if/else loops?
To fix your code with minimal changes, change return func(x, args) to return func(x, *args). I think this is what Anton vBR is suggesting in the comments.
However, I think your code could be further simplified by
using the * ("splat") and ** ("double-splat"?) positional/keyword argument unpacking operators like this:
def func_one(x, a, b, c=0):
""" arbitrary function """
# c is initialized since it is necessary in func_two and has no effect in func_one
return a*x + b
def func_two(x, a, b, c):
""" arbitrary function """
return a*x**2 + b*x + c
def func(key, *args, **kwargs):
funcmap = {1: func_one, 2: func_two}
return funcmap[key](*args, **kwargs)
def pick_function(key, x=5):
""" picks and evaluates arbitrary function by key """
argmap = {1: (1, 2, 3), 2: (4, 5, 3)}
return func(key, x, *argmap[key])
print(func_one(x=5, a=1, b=2, c=3))
# 7
print(pick_function(1))
# 7
print(func(1, 5, 1, 2, 3))
# 7
print(func(1, b=2, a=1, c=3, x=5))
# 7
If I understand what you are asking, I don't know that you want to use 1, 2... as your dictionary keys anyway. You can pass the name of the function and the list of the args you want to use straight to a function and use it that way like:
def use_function(func, argList):
return (func(*argList))
print(use_function(func_one, [5, 1, 2, 3]))
or:
def use_function_2(func, argDict):
return (func(**argDict))
print(use_function_2(func_one, {'a':1, 'b':2,'x':5, 'c':3}))
And if you like you could still use a dictionary to hold numbers which correspond to functions as well. That would look like this:
def pick_function_2(key, x=5):
""" picks and evaluates arbitrary function by key """
if key != (1 or 2):
raise ValueError("key = 1 or 2")
## args = a, b, c
args_one = [1, 2, 3]
args_two = [4, 5, 3]
## function dictionary
func_dict = dict(zip([1, 2], [func_one, func_two]))
## args dictionary
args_dict = dict(zip([1, 2], [args_one, args_two]))
## apply function to args
func = func_dict[key]
args = args_dict[key]
return func(*([x] + args))
print(pick_function_2(1))
However, this is starting to get a bit confusing. I would make sure you take some time and just double check that this is actually what you want to do.
You are trying to mixing named arguments and unnamed arguments!
As rule of thumb, if you pass a dict to a function using ** notation, you can access the arguments using **kwargs value. However, if you pass a tuple to the funcion using * notation, you can access the arguments using *args value.
I edited the method in the following way:
def func_one(*args, **kwargs):
""" arbitrary function """
# c is initialized since it is necessary in func_two and has no effect in func_one
if args:
print("args: {}".format(args))
x, other_args, *_ = args
a, b , c = other_args
elif kwargs:
print("kwargs: {}".format(kwargs))
x, a , b , c = kwargs['x'], kwargs['a'], kwargs['b'], kwargs['c']
return a*x + b
So, in the first call you have:
print(func_one(x=5, a=1, b=2, c=3)) # prints 7
kwargs: {'b': 2, 'a': 1, 'x': 5, 'c': 3}
7
Because you are passing named arguments.
In the second execution, you'll have:
print(pick_function(1))
args: (5, (1, 2, 3))
7
I know you wanted to find a solution without if/else, but you have to discriminate between theese two cases.

Resources