Can't make properties work within nested methods - python

Im trying to create a class with some formatting options. But i can't figure out how to do it properly...
The code produced the following error:
AttributeError: 'NoneType' object has no attribute 'valuesonly'
class Testings(object):
def format_as_values_only(self,somedata):
buildstring=somedata.values()
return buildstring
def format_as_keys_only(self):
pass
def format_as_numbers(self):
pass
def get_data_method(self):
self.data= {'2_testkey':'2_testvalue',"2_testkey2":"2_testvalue2"}
#property
def valuesonly(self):
return format_as_values_only(self.data)
test=Testings()
print test.get_data_method().valuesonly
The important thing for me is to be able to get the formatters like: class.method.formatter or so...
Thanks a lot for any hints!

get_data_method has no return value, so the result of test.get_data_method() is None. That's why you're getting that exception.
If you really want to do something like test.get_data_method().valuesonly, either define the valuesonly property on Testings, and have get_data_method return self, or have get_data_method return some new object with the properties that you want defined.

You can't do things this way. Methods are just functions defined directly inside a class block. Your function is inside another function, so it's not a method. The property decorator is useless except in a class block.
But, more fundamentally, function definitions just create local names, the same as variable assignments or anything else. Your valuesonly function is not accessible at all from outside the get_data_method function, because nothing from within a function is accessible except its return value. What you have done is no different than:
def get_data_method(self):
a = 2
. . . and then expecting to be able to access the local variable a from outside the function. It won't work. When you call get_data_method(), you get the value None, because get_data_method doesn't return anything. Anything you subsequently do with the result of get_data_method() is just operating on that same None value.
If you want to access things using the syntax you describe, you will need to make get_data_method return an object that has properties like valuesonly. In other words, write another class that provides a valuesonly property, and have get_data_method return an instance of that class. A rough outline (untested):
class DataMethodGetter(object):
def __init__(self, parent):
self.parent = parent
#property
def valuesonly(self):
return format_as_values_only(self.parent.data)
class Testings(object):
# rest of class def here
def get_data_method(self):
self.data = {'blah': 'blah'}
return DataMethodGetter(self)
However, you should think about why you want to do this. It's likely to be simpler to set it up to just call valuesonly directly on the Testing object, or to pass a flag to get_data_method, doing something like get_data_method(valuesonly=True).

Related

Python Function that creates class instances

Hello i want to create a function which creates instances of a class
def make_instance(name_instance)
name_instance=puppy()
class puppy:
def __init__(self,name):
self.name =name
make_instance(cloud)
# when i pass an argument it says the variable is undefined and i use #isinstance() it return False.
Your puppy class needs to take a name value into its constructor, and you're currently not passing in anything.
Also your function doesn't return the instance at all. It simply re-assigns the instance to the variable name_instance that you pass in (losing your input). The return value of make_instance right now is None
My guess is that you want your implementation to look like the following
def make_instance(name_instance)
return puppy(name_instance)
I do want to point out though that this function isn't useful unless it does more than just create the instance, you're just adding wrapper code around the constructor

How to know which next attribute is requested in python

I have class with custom getter, so I have situations when I need to use my custom getter, and situations when I need to use default.
So consider following.
If I call method of object c in this way:
c.somePyClassProp
In that case I need to call custom getter, and getter will return int value, not Python object.
But if I call method on this way:
c.somePyClassProp.getAttributes()
In this case I need to use default setter, and first return need to be Python object, and then we need to call getAttributes method of returned python object (from c.somePyClassProp).
Note that somePyClassProp is actually property of class which is another Python class instance.
So, is there any way in Python on which we can know whether some other methods will be called after first method call?
No. c.someMethod is a self-contained expression; its evaluation cannot be influenced by the context in which the result will be used. If it were possible to achieve what you want, this would be the result:
x = c.someMethod
c.someMethod.getAttributes() # Works!
x.getAttributes() # AttributeError!
This would be confusing as hell.
Don't try to make c.someMethod behave differently depending on what will be done with it, and if possible, don't make c.someMethod a method call at all. People will expect c.someMethod to return a bound method object that can then be called to execute the method; just define the method the usual way and call it with c.someMethod().
You don't want to return different values based on which attribute is accessed next, you want to return an int-like object that also has the required attribute on it. To do this, we create a subclass of int that has a getAttributes() method. An instance of this class, of course, needs to know what object it is "bound" to, that is, what object its getAttributes() method should refer to, so we'll add this to the constructor.
class bound_int(int):
def __new__(cls, value, obj):
val = int.__new__(cls, value)
val.obj = obj
return val
def getAttributes(self):
return self.obj.somePyClassProp
Now in your getter for c.somePyClassProp, instead of returning an integer, you return a bound_int and pass it a reference to the object its getAttributes() method needs to know about (here I'll just have it refer to self, the object it's being returned from):
#property
def somePyClassProp(self):
return bound_int(42, self)
This way, if you use c.somePyPclassProp as an int, it acts just like any other int, because it is one, but if you want to further call getAttributes() on it, you can do that, too. It's the same value in both cases; it just has been built to fulfill both purposes. This approach can be adapted to pretty much any problem of this type.
It looks like you want two ways to get the property depending on what you want to do with it. I don't think there's any inherent Pythonic way to implement this, and you therefore need to store a variable or property name for each case. Maybe:
c.somePyClassProp
can be used in the __get__ and
c.somePyClassProp__getAttributes()
can be implemented in a more custom way inside the __getattribute__ function.
One way I've used (which is probably not the best) is to check for that exact variable name:
def __getattribute__(self, var_name):
if ('__' in var_name):
var_name, method = var_name.split('__')
return object.__getattribute__(self, var_name).__getattribute__(method)
Using object.__get__(self, var_name) uses the object class's method of getting a property directly.
You can store the contained python object as a variable and the create getters via the #property dectorator for whatever values you want. When you want to read the int, reference the property. When you want the contained object, use its variable name instead.
class SomePyClass(object):
def getInt(self):
return 1
def getAttributes(self):
return 'a b c'
class MyClass(object):
def __init__(self, py_class):
self._py_class = py_class
#property
def some_property(self):
return self._py_class.getInt()
x = MyClass(SomePyClass())
y = self.some_property
x._py_class.getAttributes()

How to access call parameters and arguments with __getattr__

I have the following code, where most of the code seem to look awkward, confusing and/or circumstantial, but most of it is to demonstrate the parts of the much larger code where I have a problem with. Please read carefully
# The following part is just to demonstrate the behavior AND CANNOT BE CHANGED UNDER NO CIRCUMSTANCES
# Just define something so you can access something like derived.obj.foo(x)
class Basic(object):
def foo(self, x=10):
return x*x
class Derived(object):
def info(self, x):
return "Info of Derived: "+str(x)
def set(self, obj):
self.obj = obj
# The following piece of code might be changed, but I would rather not
class DeviceProxy(object):
def __init__(self):
# just to set up something that somewhat behaves as the real code in question
self.proxy = Derived()
self.proxy.set(Basic())
# crucial part: I want any attributes forwarded to the proxy object here, without knowing beforehand what the names will be
def __getattr__(self, attr):
return getattr(self.proxy, attr)
# ======================================
# This code is the only I want to change to get things work
# Original __getattr__ function
original = DeviceProxy.__getattr__
# wrapper for the __getattr__ function to log/print out any attribute/parameter/argument/...
def mygetattr(device, key):
attr = original(device, key)
if callable(attr):
def wrapper(*args, **kw):
print('%r called with %r and %r' % (attr, args, kw))
return attr(*args, **kw)
return wrapper
else:
print "not callable: ", attr
return attr
DeviceProxy.__getattr__ = mygetattr
# make an instance of the DeviceProxy class and call the double-dotted function
dev = DeviceProxy()
print dev.info(1)
print dev.obj.foo(3)
What I want is to catch all method calls to DeviceProxy to be able to print all arguments/parameters and so on. In the given example, this works great when calling info(1), all of the information is printed.
But when I call the double-dotted function dev.obj.foo(3), I only get the message that this is not a callable.
How can I modify the above code so I also get my information in the second case? Only the code below the === can be modified.
You have just a __getattr__ on dev and you want, from within this __getattr__, to have access to foo when you do dev.obj.foo. This isn't possible. The attribute accesses are not a "dotted function" that is accessed as a whole. The sequence of attribute accesses (the dots) is evaluated one at a time, left to right. At the time that you access dev.obj, there is no way to know that you will later access foo. The method dev.__getattr__ only knows what attributes you are accessing on dev, not what attributes of that result you may later access.
The only way to achieve what you want would be to also include some wrapping behavior in obj. You say you can't modify the "Base"/"Derived" classes, so you can't do it that way. You could, in theory, have DeviceProxy.__getattr__ not return the actual value of the accessed attribute, but instead wrap that object in another proxy and return the proxy. However, that could get a bit tricky and make your code more difficult to understand and debug, since you could wind up with tons of objects being wrapped in thin proxies.

Is it bad practice to put stuff into new function properties?

Say I have a class and a function:
class AddressValidator(self):
def __init__(self):
pass
def validate(address):
# ...
def validate_address(addr):
validator = AddressValidator()
return validator.validate(addr)
The function is a shortcut for using the class, if you will. Now, what if this function has to be run thousands of times? If the validator class actually has to do something on instantiation, like connecting to a database, creating it over and over thousands of times is pretty wasteful. I was wondering if I could perhaps do something like this:
def validate_address(addr):
if not hasattr(validate_address, 'validator'):
validate_address.validator = AddressValidator()
validator = validate_address.validator
return validator.validate(addr)
Now the validator class is only instantiated once and saved "in the function", to put it that way. I've never seen this done though, so I'm guessing it's bad practice. If so, why?
Note: I know I can just cache the validator object in a module global. I'm just curious if this is a viable solution when I want to avoid littering my module.
Despite "everithing is an object", not everithing work as nice as instances of well controlled class.
This problem looks like typical case for "functor" or "callable object" as it called in python.
the code will be look something like
class AddressValidator(self):
def __init__(self):
pass
def __call__(self,address):
# ...
validate_address = AdressValidator()
or you could just define your function as shortcut to bound method
class AddressValidator(self):
def __init__(self):
pass
def validate(self,address):
# ...
validate_adress = AdressValidator().validate
I'd go with a default argument (evaluated once at function definition time and bound to the function):
def validate_address(addr, validator=AddressValidator())
return validator.validate(addr)
This is perfectly acceptable if instances of AddressValidator are considered immutable (i.e. they don't contain methods that modify their internal state), and it also allows you to later override the choice of validator should you find the need to (e.g. to provide a validator specialized for a particular country).

How does asigning of #property works? (Assigning of a getter to another variable.)

I have code like this:
class Debug(object):
...
#property
def ThreadAwareLogger(self):
if not self.logger_instance_for_current_thread:
self.logger_instance_for_current_thread=self.cloneMainLogger()
return self.logger_instance_for_current_thread
def cloneMainLogger(self):
return logger_instance_for_current_thread
class SomeOtherClass(object):
def __init__(self):
...
self.logger=debug.ThreadAwareLogger
def otherMethod(self):
...
self.logger.info("Message")
The problematic thing is the assignment self.logger=debug.ThreadAwareLogger. I'm not sure what is gonna be content of self.logger. I want it to be the whole getter and I want to have the getter executed everytime when I use self.logger in SomeOtherClass. But I'm affraid that in self.logger will be stored just the result of the getter logger_instance_for_current_thread. That means logger of the thread which was active at the time of assignment. This logger doesn't have to be the right one when I call self.logger.info("Message").
How to get the getter ThreadAwareLogger executed everytime when I call self.logger.info("Message")?
Sidenote:
Why I actually need the shortcut self.logger?
When I decide to replace ThreadAwareLogger with AdvancedThreadAwareLogger I will change just one assignment instead of thousand calls of self.logger.info("Message"). Also is None of the business of the otherMethod to care about which logger will be used.
Edit:
The assignment of getter works as described in the answer by #unutbu. But assigning of the getter causes an issue I didn't think before.
From the ThreadAwareLogger I actually call method cloneMainLogger. Now the call of someOtherClass.logger ends with exception: AttributeError: 'SomeOtherClass' object has no attribute 'cloneMainLogger'.
So far I bypassed the issue with a small hack. The SomeOtherClass actually has a Debug instance. So I call debug.cloneMainLogger() instead of self.cloneMainLogger() inside of ThreadAwareLogger. The program now works, but I consider it really dirty.
Edit 2:
If I add line self.comptreeLogger=Debug.ThreaAwareLogger inside of a method; e.g. cloneMainLogger I'm getting AttributeError: 'property' object has no attribute 'debug'.
Conclusion: I still don't understand the solution.
One way to get the whole property would be to just make another property:
class SomeOtherClass:
#property
def logger(self):
return self.debug.ThreadAwareLogger
There might be other ways, too.
import logging
import random
class Debug(object):
#property
def ThreadAwareLogger(self):
loggers = [logging.getLogger('abc'),logging.getLogger('def')]
return self.anotherDebugMethod(loggers)
def anotherDebugMethod(self,loggers):
return random.choice(loggers)
class SomeOtherClass(object):
def __init__(self):
self.debug=Debug()
#property
def logger(self):
return self.debug.ThreadAwareLogger
def otherMethod(self):
self.logger.info('Message')
if __name__=='__main__':
logging.basicConfig(level=logging.DEBUG)
x=SomeOtherClass()
for i in range(5):
x.otherMethod()
yields output like:
INFO:def:Message
INFO:abc:Message
INFO:def:Message
INFO:def:Message
INFO:abc:Message
Notice the changes in abc and def show that the Debug.ThreadAwareLogger function is getting called each time.
self.logger will refer to what is returned by the property ThreadAwareLogger, not to the property itself.

Categories

Resources