Advanced Function and Class Concepts in Python
Table of Contents:
Functions
Function inside a function
This is an easy concept almost any programming language has:
def count():
def count_to(n):
for i in range(1, n+1):
print(i)
count_to(3)
count()
Out:
1
2
3
Closure
A closure is very similar to simple nested function, except it references one or more variables from its enclosing scope.
def count():
n=3
def count_to(n):
for i in range(1, n+1):
print(i)
count_to(n)
count()
Out:
1
2
3
Methods and functions difference
Python built-in type()
can provide good debugging information.
Example:
class C:
def __init__(self, name, age):
self.name = name
self.age = age
def m1(self, x):
print("Excellent {}".format(x))
@classmethod
def m2(cls, x):
print("Excellent cls {}".format(x))
@staticmethod
def m3(x):
print("Excellent static {}".format(x))
ci=C("John", 36)
L=dir(C) # c is a class
for i in L:
print("C::", i, type(eval('ci.'+i)))
Output:
C:: m1 <class 'method'>
C:: m2 <class 'method'>
C:: m3 <class 'function'>
On the other hand we know that anything we define out-of-the-class with def keyword is a function:
def foo():
pass
type(foo) # function
Function decorators
Function decorators allow you to execute code before and after the function itself. Here is a basic example.
def decorator1(func):
def stub():
print("before f1")
func()
print("after f1")
return stub
@decorator1
def f1():
print("f1")
f1()
Out:
before f1
f1
after f1
Partials
Partials are imported from functools
. They enable you to create new kind of functions or classes of type (functools.partial).
This new function will have some implicit parameters.
The partial is like a function without a body, entirely dependent on the host function being specified, but with some parameter predefined.
Example:
from functools import partial
def multiply(x,y): return x * y
# create a new kind of function that multiplies by 2
fdouble = partial(multiply,2)
fdouble(4)
Out:
8
type(fdouble)
Out:
functools.partial
Classes
Partials
Partials are not just functions, they can help us define a class:
from functools import partial
class C:
def __init__(self, a,b):
pass
c = C(1,2)
print(type(c))
cp = partial(C,1)
print(cp)
print(type(cp))
def fun1(a,b,c):
print(a,b,c)
return a+b+c
fun2 = partial(fun1,c=3)
fun2(4,5)
print(fun2)
print(type(fun2))
Out:
<class '__main__.C'>
functools.partial(<class '__main__.C'>, 1)
<class 'functools.partial'>
4 5 3
functools.partial(<function fun1 at 0x00000298EA515708>, c=3)
<class 'functools.partial'>
Print public methods of a class
You can use inspect module:
class SimulationApi(object):
def hello(self):
return "Hi"
def echo(self, string):
return string
def get_foo(self):
return self.foo
def __init__(self):
self.foo = 50
import inspect
inspect.getmembers(SimulationApi)
Out:
[('__class__', type),
('__delattr__', <slot wrapper '__delattr__' of 'object' objects>),
('__dict__',
mappingproxy({'__module__': '__main__',
'hello': <function __main__.SimulationApi.hello(self)>,
'echo': <function __main__.SimulationApi.echo(self, string)>,
'get_foo': <function __main__.SimulationApi.get_foo(self)>,
'__init__': <function __main__.SimulationApi.__init__(self)>,
'__dict__': <attribute '__dict__' of 'SimulationApi' objects>,
'__weakref__': <attribute '__weakref__' of 'SimulationApi' objects>,
'__doc__': None})),
('__dir__', <method '__dir__' of 'object' objects>),
('__doc__', None),
('__eq__', <slot wrapper '__eq__' of 'object' objects>),
('__format__', <method '__format__' of 'object' objects>),
('__ge__', <slot wrapper '__ge__' of 'object' objects>),
('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>),
('__gt__', <slot wrapper '__gt__' of 'object' objects>),
('__hash__', <slot wrapper '__hash__' of 'object' objects>),
('__init__', <function __main__.SimulationApi.__init__(self)>),
('__init_subclass__', <function SimulationApi.__init_subclass__>),
('__le__', <slot wrapper '__le__' of 'object' objects>),
('__lt__', <slot wrapper '__lt__' of 'object' objects>),
('__module__', '__main__'),
('__ne__', <slot wrapper '__ne__' of 'object' objects>),
('__new__', <function object.__new__(*args, **kwargs)>),
('__reduce__', <method '__reduce__' of 'object' objects>),
('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>),
('__repr__', <slot wrapper '__repr__' of 'object' objects>),
('__setattr__', <slot wrapper '__setattr__' of 'object' objects>),
('__sizeof__', <method '__sizeof__' of 'object' objects>),
('__str__', <slot wrapper '__str__' of 'object' objects>),
('__subclasshook__', <function SimulationApi.__subclasshook__>),
('__weakref__', <attribute '__weakref__' of 'SimulationApi' objects>),
('echo', <function __main__.SimulationApi.echo(self, string)>),
('get_foo', <function __main__.SimulationApi.get_foo(self)>),
('hello', <function __main__.SimulationApi.hello(self)>)]
Your methods (the methods you like to get info) are also the
SimulationApi
class dictionary dict.
You can get the full code for your echo()
function like this:
import inspect
lines = inspect.getsource(SimulationApi.echo)
print(lines)
def echo(self, string):
return string
Printing class types
Example:
class test(object):
def __init__(self):
self.a = 1
self.b = "abc"
test_obj = test()
print(vars(test_obj))
for k, v in vars(test_obj).items():
print('variable is {0}: and variable value is {1}, of type {2}'.format(k,v, type(v)))
Out:
{'a': 1, 'b': 'abc'}
variable is a: and variable value is 1, of type <class 'int'>
variable is b: and variable value is abc, of type <class 'str'>
Get class variables without instantiating
It is possible to do that using the type
keyword in Python. There you have the example like this:
class X:
a = 1
X = type('X', (object,), dict(a=1))
print(X)
Out:
<class '__main__.X'>
What is class dict?
Class dict is a mappingproxy. A mappingproxy is simply a dict with no __setattr__
method.
You can check out and refer to this code.
from types import MappingProxyType
d={'key': "value"}
m = MappingProxyType(d)
print(type(m)) # <class 'mappingproxy'>
m['key']='new' #TypeError: 'mappingproxy' object does not support item assignment
mappingproxy is since Python 3.3. The following code shows dict types:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
How to add property to a class dynamically?
class C:
def __init__(self):
self._x=None
def g(self):
return self._x
def s(self, x):
self._x = x
def d(self):
del self._x
def s2(self,x):
self._x=x+x
x=property(g,s,d)
c = C()
c.x="a"
print(c.x)
C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x)
Out:
a
aa
getattr(object, 'x')
is completely equivalent toobject.x
.
Appendix
Printing
Python dir
command can’t provide you all. It’s just a list of what you have inside a module.
How to provide also the type of the object?
import matplotlib.pyplot as plt
# type(plt) # module
# dir(plt) # what is in the plot object
d=dir(plt)
def dirtype(d):
for i in d:
print(i, type(eval('plt.'+i)))
dirtype(d)
Out:
Annotation <class 'type'>
Arrow <class 'type'>
Artist <class 'type'>
AutoLocator <class 'type'>
Axes <class 'type'>
Button <class 'type'>
Circle <class 'type'>
Figure <class 'type'>
FigureCanvasBase <class 'type'>
FixedFormatter <class 'type'>
FixedLocator <class 'type'>
FormatStrFormatter <class 'type'>
Formatter <class 'type'>
FuncFormatter <class 'type'>
GridSpec <class 'type'>
IndexLocator <class 'type'>
Line2D <class 'type'>
LinearLocator <class 'type'>
Locator <class 'type'>
LogFormatter <class 'type'>
LogFormatterExponent <class 'type'>
LogFormatterMathtext <class 'type'>
LogLocator <class 'type'>
MaxNLocator <class 'type'>
MultipleLocator <class 'type'>
Normalize <class 'type'>
NullFormatter <class 'type'>
NullLocator <class 'type'>
Number <class 'abc.ABCMeta'>
PolarAxes <class 'type'>
Polygon <class 'type'>
Rectangle <class 'type'>
ScalarFormatter <class 'type'>
Slider <class 'type'>
Subplot <class 'type'>
SubplotTool <class 'type'>
Text <class 'type'>
TickHelper <class 'type'>
Widget <class 'type'>
_INSTALL_FIG_OBSERVER <class 'bool'>
_IP_REGISTERED <class 'function'>
__builtins__ <class 'dict'>
__cached__ <class 'str'>
__doc__ <class 'str'>
__file__ <class 'str'>
__loader__ <class '_frozen_importlib_external.SourceFileLoader'>
__name__ <class 'str'>
__package__ <class 'str'>
__spec__ <class '_frozen_importlib.ModuleSpec'>
_auto_draw_if_interactive <class 'function'>
_backend_mod <class 'module'>
_get_running_interactive_framework <class 'function'>
_interactive_bk <class 'list'>
_log <class 'logging.Logger'>
_pylab_helpers <class 'module'>
_setp <class 'function'>
_setup_pyplot_info_docstrings <class 'function'>
_show <class 'function'>
acorr <class 'function'>
angle_spectrum <class 'function'>
annotate <class 'function'>
arrow <class 'function'>
autoscale <class 'function'>
autumn <class 'function'>
axes <class 'function'>
axhline <class 'function'>
axhspan <class 'function'>
axis <class 'function'>
axvline <class 'function'>
axvspan <class 'function'>
bar <class 'function'>
barbs <class 'function'>
barh <class 'function'>
bone <class 'function'>
box <class 'function'>
boxplot <class 'function'>
broken_barh <class 'function'>
cbook <class 'module'>
cla <class 'function'>
clabel <class 'function'>
clf <class 'function'>
clim <class 'function'>
close <class 'function'>
cm <class 'module'>
cohere <class 'function'>
colorbar <class 'function'>
colormaps <class 'function'>
connect <class 'function'>
contour <class 'function'>
contourf <class 'function'>
cool <class 'function'>
copper <class 'function'>
csd <class 'function'>
cycler <class 'function'>
dedent <class 'function'>
delaxes <class 'function'>
deprecated <class 'function'>
disconnect <class 'function'>
docstring <class 'module'>
draw <class 'function'>
draw_all <class 'method'>
draw_if_interactive <class 'function'>
errorbar <class 'function'>
eventplot <class 'function'>
figaspect <class 'function'>
figimage <class 'function'>
figlegend <class 'function'>
fignum_exists <class 'function'>
figtext <class 'function'>
figure <class 'function'>
fill <class 'function'>
fill_between <class 'function'>
fill_betweenx <class 'function'>
findobj <class 'function'>
flag <class 'function'>
functools <class 'module'>
gca <class 'function'>
gcf <class 'function'>
gci <class 'function'>
get <class 'function'>
get_backend <class 'function'>
get_cmap <class 'function'>
get_current_fig_manager <class 'function'>
get_figlabels <class 'function'>
get_fignums <class 'function'>
get_plot_commands <class 'function'>
get_scale_docs <class 'function'>
get_scale_names <class 'function'>
getp <class 'function'>
ginput <class 'function'>
gray <class 'function'>
grid <class 'function'>
hexbin <class 'function'>
hist <class 'function'>
hist2d <class 'function'>
hlines <class 'function'>
hot <class 'function'>
hsv <class 'function'>
importlib <class 'module'>
imread <class 'function'>
imsave <class 'function'>
imshow <class 'function'>
inferno <class 'function'>
inspect <class 'module'>
install_repl_displayhook <class 'function'>
interactive <class 'function'>
ioff <class 'function'>
ion <class 'function'>
isinteractive <class 'function'>
jet <class 'function'>
legend <class 'function'>
locator_params <class 'function'>
logging <class 'module'>
loglog <class 'function'>
magma <class 'function'>
magnitude_spectrum <class 'function'>
margins <class 'function'>
matplotlib <class 'module'>
matshow <class 'function'>
minorticks_off <class 'function'>
minorticks_on <class 'function'>
mlab <class 'module'>
new_figure_manager <class 'method'>
nipy_spectral <class 'function'>
np <class 'module'>
pause <class 'function'>
pcolor <class 'function'>
pcolormesh <class 'function'>
phase_spectrum <class 'function'>
pie <class 'function'>
pink <class 'function'>
plasma <class 'function'>
plot <class 'function'>
plot_date <class 'function'>
plotfile <class 'function'>
plotting <class 'function'>
polar <class 'function'>
prism <class 'function'>
psd <class 'function'>
pylab_setup <class 'function'>
quiver <class 'function'>
quiverkey <class 'function'>
rc <class 'function'>
rcParams <class 'matplotlib.RcParams'>
rcParamsDefault <class 'matplotlib.RcParams'>
rcParamsOrig <class 'matplotlib.RcParams'>
rc_context <class 'function'>
rcdefaults <class 'function'>
rcsetup <class 'module'>
re <class 'module'>
register_cmap <class 'function'>
rgrids <class 'function'>
savefig <class 'function'>
sca <class 'function'>
scatter <class 'function'>
sci <class 'function'>
semilogx <class 'function'>
semilogy <class 'function'>
set_cmap <class 'function'>
set_loglevel <class 'function'>
setp <class 'function'>
show <class 'function'>
silent_list <class 'type'>
specgram <class 'function'>
spring <class 'function'>
spy <class 'function'>
stackplot <class 'function'>
stem <class 'function'>
step <class 'function'>
streamplot <class 'function'>
style <class 'module'>
subplot <class 'function'>
subplot2grid <class 'function'>
subplot_tool <class 'function'>
subplots <class 'function'>
subplots_adjust <class 'function'>
summer <class 'function'>
suptitle <class 'function'>
switch_backend <class 'function'>
sys <class 'module'>
table <class 'function'>
text <class 'function'>
thetagrids <class 'function'>
tick_params <class 'function'>
ticklabel_format <class 'function'>
tight_layout <class 'function'>
time <class 'module'>
title <class 'function'>
tricontour <class 'function'>
tricontourf <class 'function'>
tripcolor <class 'function'>
triplot <class 'function'>
twinx <class 'function'>
twiny <class 'function'>
uninstall_repl_displayhook <class 'function'>
violinplot <class 'function'>
viridis <class 'function'>
vlines <class 'function'>
waitforbuttonpress <class 'function'>
warn_deprecated <class 'function'>
winter <class 'function'>
xcorr <class 'function'>
xkcd <class 'function'>
xlabel <class 'function'>
xlim <class 'function'>
xscale <class 'function'>
xticks <class 'function'>
ylabel <class 'function'>
ylim <class 'function'>
yscale <class 'function'>
yticks <class 'function'>
…
tags: advanced & category: python