Is there a method/interface specific for an attribute in Python? - python

Is there any way to have a method which processes the attributes and returns the desired value in python?
Below is the example of what i want to achieve.
class Foo():
self.a = '123'
self.b = '234'
def hex_value(self,attribute): # method for attribute.
return hex(attribute)
if __name__=="__main__":
obj = Foo()
print(obj.a.hex) # should give hex value of 'a' by simply using dot operator.

I feel a little dirty by hacking someting like this together, but you could use some kind of proxy class to do this:
class Proxy():
def __init__(self, value, parent):
self.value = value
self.parent = parent
def __getattr__(self, attr):
return self.parent.__getattribute__(attr + '_value')(self.value)
class Foo():
def __init__(self):
self.a = '123'
self.b = '234'
self.c = 'foo_Bar'
def hex_value(self,attribute):
return hex(int(attribute))
def repeated_value(self,attribute):
return attribute + " " + attribute + " " + attribute
def __getattribute__(self, attr):
if not attr.endswith('_value') and not attr.startswith('__'):
return Proxy(super(Foo, self).__getattribute__(attr), self)
return super(Foo, self).__getattribute__(attr)
if __name__=="__main__":
obj = Foo()
print(obj.a.hex) # should give hex value of 'a' by simply using dot operator.
print(obj.c.repeated) # prints 'foo_Bar foo_Bar foo_Bar'
The idea is that everything that you access in Foo is wrapped in a proxy. And everything you access in the proxy that's not avaiable is called on the proxy's creator (with an '_value' added) instead.
But just because you can doesn't mean you should.

Related

How to create class from which I can use "get"?

In Python, I am trying to create a class that has attributes which I can "get" (sorry if this wording is not exactly correct).
Basically I am trying to define some class p which has attributes var1 and var2. So then I can use p.get("var1") and p.get("var2") to get the values of these respective attributes. How can I define something like this?
You can define a class with get() method and check if the instance has the attribute with built-in getattr() method as following:
class MyClass:
def get(self, property, default=None):
return getattr(self, property, default)
var1 = 'var1'
var2 = 'var2'
myInstance = MyClass()
print(myInstance.get('var1'))
print(myInstance.get('var3', 'NonExisting Attribute'))
Here's a working repl.it project that I just created: https://repl.it/#HarunYlmaz/OvalLiveMethod
You can also check if the instance has the attribute with hasattr() method:
class MyClass:
def get(self, property, default=None):
if hasattr(self, property):
return getattr(self, property)
else:
return default
# Or you can raise an exception here
For instance object
class Test:
def __init__(self):
self.a = 1
self.b = 2
def get(self, var):
return eval('self.%s' % var)
t = Test()
a = t.get('a')
print(a) ## output: 1
For class object
class Test:
a = 1
b = 2
#classmethod
def get(cls, var):
return eval('cls.%s' % var)
a = Test.get('a')
print(a) # output: 1

How to make an array of functions callable in python

I'm trying to create a class A which is basically a list of objects B.
I would like to be able to call a method in A which automatically
returns a list of the corresponding method in B:
A.method(x) = [B.method(x) for B in A]
The issue is that I need a dynamical behavior, so any method in B is
automatically "inherited" by A without having to hard code it.
I have tried using lambda functions and exec("""def ..."""),
but nothing seems to work. Here is an attempt:
class A(object):
def __init__(self,Bs):
self.listOfBs = Bs[:]
if self.listOfBs:
for method_name in dir(self.listOfBs[0]):
if not callable(getattr(self.listOfBs[0],method_name)):
continue
f = lambda x: [getattr(B,method_name)(x) for B in self.listOfBs]
setattr(self,method_name,f)
class B(object):
def __init__(self,name):
self.name = name
def getName(self,x):
return self.name+x
#So if I define:
a = A([B('x'),B('y'),B('z')])
#I would like to have: a.getName('W') = ['xW','yW','zW']
#However I get the error: TypeError: 'str' object is not callable
I think there should be an easy/elegant way of implementing the above behavior in python, but I couldn't find anything that works.
You may use __getattr__ to make method lookup dynamic
class A:
def __init__(self, bs):
self.bs = bs
def __getattr__(self, method_name):
def call(*args, **kw):
return [getattr(b, method_name)(*args, **kw) for b in bs]
return call
Thanks a lot. I had tried getattr before, but was missing some steps.
Just for the record, following Glazner's suggestion here is a working solution, which works both with attributes and methods:
class A(object):
def __init__(self,Bs):
self.listOfBs = Bs[:]
def __getattr__(self, attr):
if not all(hasattr(b,attr) for b in self.listOfBs):
raise AttributeError("Attribute %s not found." %attr)
val = getattr(self.listOfBs[0],attr)
if not callable(val):
return np.array([getattr(b,attr) for b in self.listOfBs])
def call(*args, **kw):
return [getattr(b, attr)(*args, **kw) for b in self.listOfBs]
return call
class B(object):
def __init__(self,name):
self.name = name
def getName(self,x):
return self.name+x
a = A([B('x'),B('y'),B('z')])
a.name #Returns ['x','y','z']
a.getName('W') #Returns ['xW','yW','zW']

Can't get method name when using decorator

I suppose I'm missing something obvious, but I can't get the name of methods when I'm using decorators. When I run this code, I get the error:
AttributeError: 'str' object has no attribute "__name__"
Could somebody tell me how I can get the name of these decorated method?
Thanks
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob(object):
def __init__(self):
pass
#property
def stuff(self):
return "value from stuff property"
#stuff.setter
def stuff(self, noise):
return noise
class Tester:
def __init__(self):
self.dylan = Bob()
def randomTest(self):
Print(self.dylan.stuff, 1)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
stuff isn't a function or a method; it's a property. The syntax
#property
def stuff(...):
...
creates an instance of the property class using stuff as the argument to property, equivalent to
def stuff(...):
....
stuff = property(stuff)
and instances of property don't have a __name__ attribute, as you've seen.
(It's a little trickier with the setter, since the function and the property have to have the same name. But defining stuff a "second" time doesn't override the existing property named stuff.)
The individual methods are accessed via attributes of the property.
>>> Bob.stuff.fget.__name__
'stuff'
>>> Bob.stuff.fset.__name__
'stuff'
Note another, longer, way to create the same property:
class Bob:
def stuff_getter(self):
...
def stuff_setter(self, noise):
...
stuff = property(stuff_getter, stuff_setter)
del stuff_getter, stuff_setter # Clean up the namespace
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob():
def __init__(self, s):
self.stuff = s
#property
def myStuff(self):
return self.stuff
#myStuff.setter
def setStuff(self, noise):
self.stuff = noise
class Tester:
def __init__(self):
self.dylan = Bob(1)
def randomTest(self):
print(self.dylan.stuff)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
This should work :)

Can decorator wrap setter and getter in python?

I want to build various setter and getter. Fot not copy and paste the code, I thought something to solve it. Can decorator do it?
#property
def !!variable_name!!(self):
return self.__!!variable_name!!
#!!variable_name!!.setter
def !!variable_name!!(self, input):
self.__!!variable_name!! = input
Is it possible like macro in C?
It's unclear why you would want to do something like this—create a property with setter that ignores its value argument—but the answer is "Yes", you can do it by creating a function that returns a custom property object:
However you can't use # syntax to apply it. Instead you have to utilize it as shown:
def attribute_property(name, input_value):
STORAGE_NAME = '_' + name
#property
def prop(self):
return getattr(self, STORAGE_NAME)
#prop.setter
def prop(self, ignored):
setattr(self, STORAGE_NAME, input_value)
return prop
# EXAMPLE USAGE
class Person(object):
name = attribute_property('name', 'Monty')
def __init__(self, name, age):
self.name = name # ignores value of passed "name" argument!
self.age = age
user = Person('Rodrigo', 42)
print('user.name: {!r}'.format(user.name))
print('user.age: {!r}'.format(user.age))
Output:
user.name: 'Monty'
user.age: 42
Simple answer: Yes, that's possible using the descriptor protocol. For example you want to save variables with a leading underscore and access them without the leading underscore such a descriptor would work:
from six import string_types
class DescriptorSingleLeadingUnderscore(object):
def __init__(self, attr, doc=""):
if not isinstance(attr, string_types):
# Not a string so take the documentation (if avaiable) and name
# from the method.
if attr.__doc__:
doc = attr.__doc__
attr = attr.__name__
self.__doc__ = doc # Set the documentation of the instance.
self.attr = '_' + attr # Add leading underscore to the attribute name
def __get__(self, instance, owner=None):
if instance is None:
return self
return getattr(instance, self.attr, None)
def __set__(self, instance, value):
setattr(instance, self.attr, value)
def __delete__(self, instance):
delattr(instance, self.attr)
class X(object):
someproperty = DescriptorSingleLeadingUnderscore('someproperty')
someproperty1 = DescriptorSingleLeadingUnderscore('someproperty1')
someproperty2 = DescriptorSingleLeadingUnderscore('someproperty2')
someproperty3 = DescriptorSingleLeadingUnderscore('someproperty3')
#DescriptorSingleLeadingUnderscore
def it_also_works_as_decorator(self):
pass # this code is never executed!
And a test case:
>>> x = X()
>>> x.someproperty = 100
>>> x.someproperty
100
>>> x._someproperty
100
>>> x.it_also_works_as_decorator = 100
>>> x.it_also_works_as_decorator
100
>>> x._it_also_works_as_decorator
100

"Private" arguments to __init__()?

I have a class that takes a single parameter a on instantiation, which is stored in the _a attribute. For a number of methods (operators), I need to set also a _b attribute on the result. This is currently implemented in a straight-forward way:
class SomeClass(object):
def __init__(self, a=0):
self._a = a
self._b = 0
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
Now, I have an number of members like _b, such as _c and _d, so __add__ will need an extra line for each of these attributes. Being able to pass these on object instantiation would result in cleaner code:
class SomeClass(object):
def __init__(self, a=0, _b=0):
self._a = a
self._b = 0
def __add__(self, other):
return self.__class__(_b=self._a + other._a)
However, I don't want the user to pass values for all of the parameters, except for a as _b, _c and _d are implementation specifics. I could simply state in the docstring not to pass more than one argument. Preceding the 'private' attributes with an underscore is intended to reflect this.
Alternatively, I can try to make it harder for the user to misbehave, by providing a second, private constructor:
class SomeClass(object):
def __init__(self, a=0):
self._a = a
self._init()
def _init(self, _b=0):
self._b = _b
#classmethod
def _constructor(cls, a, _b):
obj = cls(a)
obj._init(b)
return obj
def __add__(self, other):
return self.__class__._constructor(_b=self._a + other._a)
I'm thinking this is a rather clunky solution.
What would be the preferred way to solve this problem? Are there other, more elegant, solutions? Is this really a problem; should I just use the first option and end up with some more lines of code?
The _ underscore convention is clear and prevalent through the python world.
You document your 'public' attributes, and just use default arguments with underscores to your __init__ method. Keep it simple.
If someone wants to screw up a class by using those private parameters anyway, you are not going to stop them, not in Python.
To tidy it up a tiny bit, you could set _b before __init__:
class SomeClass(object):
_b = 0
def __init__(self, a=0):
self._a = a
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
Or if there are heaps of private variables, put them into a list and do some magic?
class SomeClass(object):
calculated_vars = ['_b'] # All your calculated variables
def __init__(self, a=0):
self._a = a
def __getattr__(self, k):
if k in self.calculated_vars:
return 0 # Default value for calculated variables
else:
raise AttributeError('{} not found'.format(k))
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
if __name__ == '__main__':
i = SomeClass(1)
print '_a attr: ', i._a # 1
print '_b attr: ', i._b # 0 (Default value)
print '_c attr: ', i._c # AttributeError: _c not found
i2 = SomeClass(3)
i3 = i + i2
print '_b attr: ', i3._b # 4 (Calculated value)

Categories