Python Override non class functions - python

with the code below when I run file a.py the output expectedly is "hello" and with file b.py I want to override bar() from a so I get a "Goodbye" as a result
My goal with this is to change a more complicated function alongside of a program while implementing simpler functions in the main program
I understand that classes would work if a.py contained a class the b imported but that is a fair bit of overhead to rework my code to be a class
file a.py:
def foo ():
print (bar())
def bar ():
return "hello"
if(__name__=='__main__'):
foo()
output
hello
file b.py:
from a import *
def bar():
return "Goodbye"
if(__name__=='__main__'):
foo()
output
hello
Class Implementation
file a_class.py
class a:
def foo (self):
print (self.bar())
def bar (self) -> str:
return "hello"
if(__name__=='__main__'):
a().foo()
output
hello
file b_class.py
from a_class import a
class b(a):
def bar (self) -> str:
return "Goodbye"
if(__name__=='__main__'):
b().foo()
output
Goodbye
edit* grammer

As everyone has mentioned my only options would be to change my code to Object Oriented or to duplicate all the dependent functions into the new module

Related

Python dependency issue

I've my scripts setup in the following way -
a.py (Newly added script)
from b import B
import c
class A(B):
def process(self):
super().method()
c.method1()
c.method2()
b.py (Existing script in Prod)
import c
class B(Exception):
def method(self):
c.method1()
c.method2()
c.py (Existing script in Prod)
def method1()...
def method2()...
The dir's that hold b.py & c.py are all in PATH in PROD host.
When I invoke a.py from a scheduler, i get 'module' object has no attribute method() error. Also method1() & method2() in b.py don't get executed.
a.py is in the same dir as b.py, so i'm assuming nothing need to be updated in PATH.
I searched here in SO and found this could be circular dependency issue, however few of the solutions that were suggested didn't work in my case.
Any suggestions on how i can fix this issue? Also what is the best way to resolve these issues if i were to create more scripts in the same dir as existing ones.
what do you expect super() to return? It's meant to be called within a method of a class, not directly within a module.
I'd expect to see a definition of class or function B in b.py, since it's what you import in a.py.
First off - don't use super().method() to access a parent's method. This isn't necessary. the process method of class A should be:
def process(self):
self.testmethod()
c.method1()
c.method2()
You haven't posted enough code to actually show the error.
When I redefine process as above, and instantiate an object of class A:
tester = A()
tester.process()
the process method works as expected.
Updating my previous response (which was about indenation)
So I've been trying to reproduce your problem. This is what I have:
a.py
from b import B
import c
class A(B):
def __init__(self):
super().__init__()
print('a init')
def process(self):
super().method()
c.method1()
c.method2()
a = A()
a.process()
b.py
import c
class B(Exception):
def __init__(self):
print('b init')
def method(self):
print('b start')
c.method1()
c.method2()
print('b done')
c.py
def method1():
print(1)
def method2():
print(2)
Invoking a.py from the commandline: python3.4 a.py my output is:
b init
a init
b start
1
2
b done
1
2
(which is what you would expect)
tl;dr: could not reproduce.

How do decorators mark a function?

I was going throught the basic Flask tutorial which has the following code:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Also I went through the basics of Python decorators from many websites including Stackoverflow Decorators
I was of the assumption that in the previous code, the function hello will be changed and decorated, and for running the application I need to call the function hello() somewhere. How does Flask determine the name of the function it has to call.
Does just wrapping the function definition with a decorator somehow marks that function? If so, how?
For example in the below code, somewhere down the line I'm calling the function I've decorated:
def decorate(foo):
print("I'm doing a lot of important stuff right now")
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
return inner
#decorate
def hello():
print("Hello")
hello()
In decorate, foo is the function you are decorating (in this case, hello). You can store the function in a list or dictionary somewhere, since it's a normal object.
For example:
decorated_functions = []
def decorate(foo):
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
decorated_functions.append(inner)
return inner
#decorate
def hello():
print("Hello")
## The above is the same as:
# def hello():
# print("Hello")
# hello = decorate(hello)
print(decorated_functions[0] == hello) # prints True
decorated_functions[0]() # prints "Some stuff 1", "Hello", and "Some stuff 2"
hello() # same as above
Decorators are actually a very simple construct in Python. The following two examples are equivalent:
#foo
def bar():
pass
def bar():
pass
bar = foo(bar)
So your definition of hello in your first example is the equivalent to this:
def hello():
return "Hello World!"
hello = app.route("/")(hello)
The double function calls might be a bit confusing so lets rewrite it like this:
_tempfn = app.route("/")
hello = _tempfn(hello)
So it should be clear now that app.route isn't actually a decorator, it's a function that creates decorators. Now what isn't obvious is what the newly decorator does. Without looking at the source for Flash, it's likely that it adds the function hello to a dictionary member of a app. So app.route is implemented something like this:
class app(object):
def route(self, path):
def decorator(fn):
self.pathmap[path] = fn
return fn
return decorator
Note that this is pretty much a condensed version of the explanation given in the link that Jon Piparsky provided.
The decorator is simply registering the function in a lookup table. Decorators don't need to modify a function in any way, there are so many other useful things, decorators can do.
In fact, decorators in python
#some_decorator
def foo():
pass
are only a short form of
def foo():
pass
foo = some_decorator(foo)
and the function some_decorator can do anything with its arguments and can return any return value, but usually returns a function.

Scope of Python Class Variable?

Are class variables essentially global variables?
Consider this example, in bar.py:
class Bar(object):
b = {}
then in foo.py:
def foo1():
import bar
bar.Bar.b["key"] = "foo1"
def foo2():
import bar
print bar.Bar.b.get("key", "foo2")
foo1()
foo2()
The "key" value is persistently "foo1."
For my purposes this seems like a global variable. But why isn't the class variable being reset or deleted between the calls to foo1 and foo2?
It's a class attribute. In your case, the dict is bound to the class Bar. Everytime you import bar, you get the same class bar.Bar (after all, it is in the bar's global namespace), and consequentially, you get the same dict bar.Bar.b.
If you want each Bar instance to have a different dict, you need to make an instance:
class Bar(object):
def __init__(self):
self.b = {}
And then:
def foo1():
import bar
bar.Bar().b["key"] = "foo1"
def foo2():
import bar
print bar.Bar().b.get("key", "foo2")
foo1()
foo2()
As far as why the module bar isn't being garbage collected, when you import something, python stores a reference to that module (see sys.modules). The next time you import that module, python picks out the proper item from sys.modules and gives you a reference to it. There are a few reasons for this.
Efficiency -- Why re-evaluate code you've already evaluated?
Sane behavior
Imagine a module with a special value:
# mod.py
CONSTANT = object()
now you want to use that in foo.py and bar.py.
# bar.py
import mod
def bar():
return mod.CONSTANT
# foo.py
import mod
import bar
if bar.bar() is mod.CONSTANT:
do_something()
If the import wasn't cached, then mod.CONSTANT could be different in foo and in bar which would be very surprising.

Call undefined method from module

I have a module where I want to call a method not defined in that module. Is it possible?
#module
def foo():
print bar()
#main
from foo import foo
def bar():
return "Foo bar"
def main():
foo.foo()
No, you cannot. Python looks up undefined names in the same module a function is defined in.
You'll have to pass in a function reference instead:
def foo(func):
print func()
then in main:
def main():
foo.foo(bar)
You could add the function from one module to the other, but passing it as a callback is probably neater. It depends on the situation.
#module
def foo(bar):
print bar()
#main
from foo import foo
def bar():
return "Foo bar"
def main():
foo(bar)

Python Decorator Scoping Issues

I have a static class that has a method hello. I want to run the decorator method bar before hello. However, using the following code I always get a "name 'bar' is not defined" error. Does anyone know what's going on? Thanks!
class foo():
#staticmethod
#bar
def hello():
print "hello"
def bar(fn):
def wrapped():
print "bar"
return fn()
return wrapped
foo.hello()
Because it's not defined yet. Besides, that decorator shouldn't be a method at all.
def bar(fn):
# ...
class foo(object):
#staticmethod
#bar
def hello():
# ...
# ...
Also, don't use static methods, unless you really know what you're doing. Make it a free function instead.
You can just change your code to:
def bar(fn):
def wrapped():
print "bar"
return fn()
return wrapped
class foo():
#staticmethod
#bar
def hello():
print "hello"
foo.hello()
This happens because you have to define a function before you call it. This is a problem because this:
#bar
def hello():
print "hello"
is equivalent to:
def hello():
print "hello"
hello = bar(hello)
So you were trying to call the function before you defined it.

Categories