Missing methods in Python class inheritance? - python

I am not very experienced with class inheritance. Please help me and have a look at the code below:
class Handle(STAFHandle):
def __init__(self, HandleName):
handle = STAFHandle.__init__(self, HandleName)
self.initLogger(handle)
def initLogger(self, handle):
self.logger = Logging(handle, 'Test')
handle = Handle('test')
handle.logger.info('test')
it says submit method is not defined:
result = handle.submit(system, service, logRequest)
AttributeError: 'NoneType' object has no attribute 'submit'
but if I change it to:
class Handle(STAFHandle):
def __init__(self, HandleName):
handle = STAFHandle.__init__(self, HandleName)
def initLogger(self, handle):
self.logger = Logging(handle, 'Test')
handle = Handle('test')
handle.initLogger(handle)
handle.logger.info('test')
it works. Why there is a difference? Thanks a lot!!
Cheers,
Zhe

STAFHandle.__init__ returns None. You probably want:
class Handle(STAFHandle):
def __init__(self, handle_name):
super(Handle, self).__init__(handle_name)
self.initLogger()
def initLogger(self):
self.logger = Logging(self, 'Test')
handle = Handle('test')
Remember that __init__ methods take as their first argument an object, and modify that object. So when you call super(Handle, self).__init__(handleName) you are changing the properties of self instead of returning a new object. The difference between your two examples is that the variable handle in the two calls to initLogger refers to different things.
Notice that I have replaced the explicit STAFHandle.__init__ call with a super proxy; this is equivalent in this case but allows for more flexibility, since you can now change the inheritance of the class without breaking its __init__.
I've also changed HandleName to handle_name to conform with Python conventions (CamelCase refers to classes).

Related

Refactor the python design patterns

I have a class called resources and I have defined one method called get_connect. I want to use the data of which get_connect returns to the other classes. I need at least three classes and I use the data of get_connect and I have to parse that data. To implement this I have written the code below
class resources:
#staticmethod
def get_connect():
return 1 + 2
class Source1(resources):
def __init__(self):
self.response = resources.get_connect()
def get__details1(self):
print(self.response)
class Source2(resources):
def __init__(self):
self.response = resources.get_connect()
def get_details2(self):
print(self.response)
class Source3(resources):
def __init__(self):
self.response = resources.get_connect()
def get__detail3(self):
print(self.response)
source1 = Source1()
source2 = Source2()
source3 = Source3()
source1.get__details1()
source2.get_details2()
source3.get__detail3()
But the problem with the code is for every class in init method I am calling the get_connect method. I don't want to repeat the code. I need help for avoiding redundancy which I have asked below
Is there any way I can call get_connect in one place and use it for other classes maybe a decorator or anything? if yes how can I?
While creating objects also I am calling each class and calling each method every time. is there a way to use any design pattern here?
If anyone helps me with these oops concepts it will be useful.
First of all, is there any reason why you are using get_connect method as static?
Because what you can do here is declare it in the parent class:
class resources:
def __init__(self):
self.response = self.get_connect()
def get_connect(self):
return 1 + 2
This way you do not need to define the __init__ method on every class, as it will be automatically inherited from the parent.
Regarding the second question, it really depends on the context, but you can use a strategy pattern in order to retrieve the class that you require to call. For this rename the method of get details into the same for each of the classes, as basically they're used for the same purpose, but changed on the context of the class implementation:
class Source1(resources):
def get_details(self):
print(self.response)
class Source2(resources):
def get_details(self):
print(self.response)
class Source3(resources):
def get_details(self):
print(self.response)
classes = {
"source_1": Source1,
"source_2": Source2,
"source_3": Source3
}
source_class = classes["source_1"]
source = source_class()
source.get_details()
Hope this helped!

Access a class attribute inside a python class decorator

EDIT: i found this method decorator and was able to use it to individually wrap the methods (omitting __init__) of ClassA and ClassB. however, instead of manually wrapping individual methods, i'd like to just wrap the class.
i've created my own logging class, MyLogger, which inherits logging.Logger. in this class, (among other things) i have a FileHandler which prints the logger name in its output:
import logging
class MyLogger(logging.Logger):
def __init__(self, name, path="output.log"):
logging.Logger.__init__(self, name, logging.DEBUG)
logpath = path
fh = logging.FileHandler(logpath)
fh.setLevel(logging.DEBUG)
fh.setFormatter(logging.Formatter("%(name)s - %(message)s"))
# stream handler omitted
self.addHandler(fh)
i also have ClassA and ClassB, which both get the same instance of MyLogger:
class ClassA(object):
def __init__(self, mylogger):
self.log = mylogger
def fn1(self):
self.log.debug("message1 from ClassA fn1")
self.fn2()
b = ClassB(self.log)
b.fn1()
self.log.debug("message2 from ClassA fn1")
def fn2(self):
self.log.debug("message1 from ClassA fn2")
# many more functions
class ClassB(object):
def __init__(self, mylogger):
self.log = mylogger
def fn1(self):
self.log.debug("message1 from ClassB fn1")
# many more functions
here's a simple "main" function:
print "inside main"
log = MyLogger("main")
a = ClassA(log)
a.fn1()
because the MyLogger instance is being passed around, i'd like to ensure the log name (i'm just using the class name) is printed correctly by each function. so i'm attempting to decorate all methods of each class so that the the previous log name is remembered, then the log name is set to the name of the class, the method is run, and finally the log name is set back to what it previously was. i'm using the decorator/descriptor from here. for the sake of brevity, i will only post my changes to it. i renamed the decorator setlogger, have added print statements inside each method in the descript class, and have altered make_bound as follows:
def make_bound(self, instance):
print "in __BOUND__"
#functools.wraps(self.f)
def wrapper(*args, **kwargs):
'''This documentation will disapear :)'''
prev = instance.log.name
print "about to wrap %s.%s, prev = %s" % (instance.__class__.__name__, self.f.__name__, prev)
ret = self.f(instance, *args, **kwargs)
instance.log.name = prev
print "done wrapping %s.%s, now = %s" % (instance.__class__.__name__, self.f.__name__, prev)
return ret
# This instance does not need the descriptor anymore,
# let it find the wrapper directly next time:
setattr(instance, self.f.__name__, wrapper)
return wrapper
if i use the setlogger decorator/descriptor to wrap individual methods in ClassA and ClassB, it works fine. however, i'd like to just wrap the two classes. so here's my class decorator:
def setloggerforallmethods(cls):
def decorate(*args, **kwargs):
for name, m in inspect.getmembers(cls, inspect.ismethod):
if name != "__init__":
print "calling setattr on %s.%s" % (cls.__name__, name)
setattr(cls, name, setlogger(m))
return cls
return decorate
if i wrap ClassA and ClassB with #setloggerforallmethods, and run the main function, heres the output:
inside main
calling setattr on ClassA.fn1
in __INIT__: f = fn1
calling setattr on ClassA.fn2
in __INIT__: f = fn2
in __GET__
in __UNBOUND__
Traceback (most recent call last):
File "/ws/maleva-rcd/yacht/classa.py", line 23, in <module>
a.fn1()
File "/ws/maleva-rcd/yacht/yachtlogger.py", line 34, in wrapper
self.f.__name__)
ValueError: zero length field name in format
i dont understand why fn1 is unbound at this time. isnt it bound to a as in a.fn1()?
I think you're trying to solve the wrong problem in the wrong way. But I can explain why your code isn't doing what you're trying to make it do.
First, in your decorator, you do this:
for name, fn in inspect.getmembers(cls, inspect.ismethod):
if name != "__init__":
print "calling setlogger on %s" % cls.__name__ + "." + name
fn = setlogger(fn)
That has no effect. For each bound method fn, you create a wrapper function, then rebind the local variable fn to that function. That has no more effect than doing this:
def foo(a):
a = 3
i = 0
foo(i)
If you want to set an attribute on the class, you have to set an attribute on the class, like this:
setattr(cls, name, setlogger(fn))
Now your wrapper will get called.
Next, cls.log is a class attribute named log—that is, an attribute on the class itself, which is shared by all instances of that class. But all of the code within the classes uses instance attributes, where each instance has its own copy. That's what you get when you assign self.log in your __init__. So, there is no class attribute named log, meaning you'll just get this:
AttributeError: type object 'ClassA' has no attribute 'log'
You could of course create a class attribute… but that won't do any good. The instance attribute of the same name will just shadow it.
You need to access the instance attribute inside inner, which means you need a self to access it off. And you obviously don't have self inside setlogger. But think about what you're doing: you're wrapping a method with another method. Methods get self as their first argument. In fact, if you modify inner to print out its args, you'll see that the first one is always something like <__main__.ClassA object at 0x12345678>. So:
def inner(self, *args, **kwargs):
prevname = self.log.name
self.log.name = cls.__name__
ret = func(self, *args, **kwargs) # don't forget to forward self
self.log.name = prevname
return ret
But if any of these wrapped methods ever raises an exception, they'll leave the name in the wrong state. So really, you need to either create a context manager for stashing and restoring the value, or just a try/finally. Which also happens to make the wrapper a little easier to write:
def inner(self, *args, **kwargs):
prevname = self.log.name
self.log.name = cls.__name__
try:
return func(self, *args, **kwargs)
finally:
self.log.name = prevname
Finally, you need to remove the self.log.name = in each __init__ method. Otherwise, when you construct a B instance in the middle of A.fn1, you're changing the logger's name without going through the wrapper that restores the previous name.
Again, I don't think this is a good solution. But it will do what you're trying to do.
I still don't completely understand the problem you're trying to solve, but I think it's this:
Constructing a MyLogger takes two pieces of information: a name, and a path. You don't want every class to have to know that path. So, you figured you needed to share the MyLogger instance, because there's no other way around that. And then, because the MyLogger stores its name as an attribute, you had to hack up that attribute in wrappers around every method.
But there is a much simpler way around that: Make your classes take a "logger factory"—that is, a callable which constructs an appropriate logger for them—instead of a logger. The MyLogger class itself already is such a callable, since it takes a default value for path and you just use it. But let's pretend that weren't true, and you wanted to use some non-default path. Still easy; you just need to wrap it up:
class ClassA(object):
def __init__(self, log_factory):
self.log_factory = log_factory
self.log = log_factory("ClassA")
def fn1(self):
# ...
b = ClassB(self.log_factory)
# ...
class ClassB(object):
def __init__(self, log_factory):
self.log_factory = log_factory
self.log = log_factory("ClassB")
# ...
# or just log_factory = functools.partial(MyLogger, log="output.log")
def log_factory(name):
return MyLogger(name, "output.log")
a = ClassA(log_factory)
a.fn1()
You may notice that the __init__ method in both classes does the same thing. So, why not extract it into a mixin base class?
class LogUserMixin(object):
def __init__(self, log_factory):
self.log_factory = log_factory
self.log = log_factory(self.__class__.__name__)
Now:
class ClassA(LogUserMixin):
def fn1(self):
# ...
When it's a ClassA being initialized, self.__class__ will be "ClassA", not "LogUserMixin", so this does exactly what you want. It works even if your real classes already have base classes, or a hierarchy of subclasses, or if they do additional stuff in __init__, or take additional arguments; you just need to do a tiny bit more work in some of those cases.

Python Class that Never Throws an AttributeError or TypeError

What is the best way to implement a class that never throws an AttributeError or TypeError?
The idea is that I have a class like this
class A():
def __init__(self):
self.logger = NeverThrowClass()
def set_logger(self, logger):
self.logger = logger
def do_stuff(self)
self.logger.info('Stuff is being done.')
pass
Whenever certain class methods are classed, we write something to a log file. However if no log file was specified, I still want the class methods to function. I realize I could catch an exception whenever self.logger is accessed, but I would rather just have the default logger attribute be some magical NeverThrowClass() that will accept being called in anyway, and politely do nothing, and return None for any attribute value so that the class will still function fine whether a logger is specified or not.
Something like this, maybe?
class DoNothing(object):
def __getattr__(self, name):
return lambda *args, **kwargs: None
Basically, this class responds to any attribute access with a function that accepts any number of arguments and returns None.
logger = DoNothing()
logger.info("Stuff is being done") # does nothing
Since it's using __getattr__() rather than the lower-level __getattribute__(), you can just throw some regular attributes on there if you want some non-method stuff.
class LoggerNot(DoNothing):
loglevel = 0
Now you have a loglevel attribute that has a reasonable value (i.e. is not a function) if you have code that checks it.

Accessing Parent Class' Property From Derived Class

I'm new to python and GAE and I thought python will act as any other OO language, but apparently not. How does __init__(self): function gives me different results in the following code?
class BaseHandler(webapp.RequestHandler):
#property
def current_user(self):
if not hasattr(self, "_current_user"):
self._current_user = None
cookie = facebook.get_user_from_cookie(self.request.cookies, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET)
user = User.get_by_key_name(cookie["uid"])
return self._current_user
class SubmitHandler(BaseHandler):
template_values = dict(facebook_app_id=FACEBOOK_APP_ID)
def __init__(self):
#throws error : AttributeError: 'SubmitHandler' object has no attribute 'request'
self.template_values['current_user'] = self.current_user
def get(self):
#this one function is error free
self.template_values['current_user'] = self.current_user
How do I access the class' parent property?
If you look at your SubmitHandler class you'll notice that it indeed does not have a request attribute -- at least, none you set, and none you give the parent class a chance to set. Perhaps what you need to do is call the parentclass __init__ method before you try to access self.current_user.
As a side note, you should realize that the template_values dict you define inside the SubmitHandler class there is a class attribute, and thus shared between all instances of the class. Since you assign it something instance-specific in your __init__, you probably mean for it to be an instance attribute instead. Assign it to self.template_values in your __init__ method.
There's nothing particularly different about Python's object inheritance.
By defining __init__, you have told Python that this is all that needs to be done to initialize the object. You're therefore denying it the chance to run the superclass's initialization code. You need to call super:
def __init__(self, *args, **kwargs):
super(SubmitHandler, self).__init__(*args, **kwargs)
self.template_values['current_user'] = self.current_user
This might however not solve your problem - you're failing to take into account the possibility that self.request is initialized at another point in the program, which is why it works by the time get is called.
self.request and self.response are not set by the class constructor in webapp. They're set later, when the framework calls the handler's initialize method. You can override this, just make sure you call the parent class's initialize before doing anything else.

How do I set and access attributes of a class? [duplicate]

This question already has answers here:
How can I access "static" class variables within methods?
(6 answers)
Closed 12 days ago.
Suppose I have this code:
class Example(object):
def the_example(self):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
When I try it, I get an error that says:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'itsProblem'
How do I access this attribute? I tried adding another method to return it:
def return_itsProblem(self):
return itsProblem
but the problem persists.
The answer, in a few words
In your example, itsProblem is a local variable.
Your must use self to set and get instance variables. You can set it in the __init__ method. Then your code would be:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
But if you want a true class variable, then use the class name directly:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
But be careful with this one, as theExample.itsProblem is automatically set to be equal to Example.itsProblem, but is not the same variable at all and can be changed independently.
Some explanations
In Python, variables can be created dynamically. Therefore, you can do the following:
class Example(object):
pass
Example.itsProblem = "problem"
e = Example()
e.itsSecondProblem = "problem"
print Example.itsProblem == e.itsSecondProblem
prints
True
Therefore, that's exactly what you do with the previous examples.
Indeed, in Python we use self as this, but it's a bit more than that. self is the the first argument to any object method because the first argument is always the object reference. This is automatic, whether you call it self or not.
Which means you can do:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
or:
class Example(object):
def __init__(my_super_self):
my_super_self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
It's exactly the same. The first argument of ANY object method is the current object, we only call it self as a convention. And you add just a variable to this object, the same way you would do it from outside.
Now, about the class variables.
When you do:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
You'll notice we first set a class variable, then we access an object (instance) variable. We never set this object variable but it works, how is that possible?
Well, Python tries to get first the object variable, but if it can't find it, will give you the class variable. Warning: the class variable is shared among instances, and the object variable is not.
As a conclusion, never use class variables to set default values to object variables. Use __init__ for that.
Eventually, you will learn that Python classes are instances and therefore objects themselves, which gives new insight to understanding the above. Come back and read this again later, once you realize that.
You are declaring a local variable, not a class variable. To set an instance variable (attribute), use
class Example(object):
def the_example(self):
self.itsProblem = "problem" # <-- remember the 'self.'
theExample = Example()
theExample.the_example()
print(theExample.itsProblem)
To set a class variable (a.k.a. static member), use
class Example(object):
def the_example(self):
Example.itsProblem = "problem"
# or, type(self).itsProblem = "problem"
# depending what you want to do when the class is derived.
If you have an instance function (i.e. one that gets passed self) you can use self to get a reference to the class using self.__class__
For example in the code below tornado creates an instance to handle get requests, but we can get hold of the get_handler class and use it to hold a riak client so we do not need to create one for every request.
import tornado.web
import riak
class get_handler(tornado.web.requestHandler):
riak_client = None
def post(self):
cls = self.__class__
if cls.riak_client is None:
cls.riak_client = riak.RiakClient(pb_port=8087, protocol='pbc')
# Additional code to send response to the request ...
Implement the return statement like the example below! You should be good. I hope it helps someone..
class Example(object):
def the_example(self):
itsProblem = "problem"
return itsProblem
theExample = Example()
print theExample.the_example()
If you have a #classmethod static method, you always have the class as the first parameter:
class Example(object):
itsProblem = "problem"
#classmethod
def printProblem(cls):
print(cls.itsProblem)
Example.printProblem()

Categories

Resources