Role of pass statement inside a function? - python

I am a newbie in object oriented programming. After defining a class we simply create objects and try to access different variables and functions inside the class. In the following code I want to know that why we again have to mention class Dataset inside the function ans secondly what is the role of pass statement?
def read_data_set():
class Dataset:
pass
data_sets = Dataset()
return(data_sets)
#Function call
x=read_data_set()
print(x)

pass does nothing, it just makes Python indentations correct.
Let's say you want to create an empty function, sth like:
def empty_func():
empty_func() # throws IndentationError
Let's try to put a comment inside:
def empty_func_with_comment():
# empty
empty_func_with_comment() # throws IndentationError
To make it work we need to fix indentations by using pass:
def empty_func_with_pass():
pass
empty_func_with_pass() # it works

It basically does nothing.
It is often used as a placeholder like in your code; you'll notice that the code does not run at all without the pass there.
class SomeClass:
pass # to be filled
This is because Python expects something to be under the definition of SomeClass, but being empty it raises an IndentationError.
class SomeClass:
# to be filled <--- empty
other_function() # <--- IndentationError
It is also used with try-except when you do not want to do anything:
try:
some_stuff()
except SomeException:
pass # I don't mind this

Why do we mention class Dataset inside the function twice?
The first time
class Dataset:
pass
the class is defined,
and the second one:
data_sets = Dataset()
an instance of this class (an object) is created. Exactly as the OP has written:
After defining a class we simply create objects.
Since class is just a python statement it can be used anywhere: including function bodies, like in this case. So here the class is defined each time the function read_data_set() is called and is not defined at all if it is not called.
What is the role of pass statement?
In this example
class Dataset:
pass
the pass statement means defining a class with no members added inside it. It means that the class and its objects contain only some "default" functions and variables (aka methods and fields) that are derived from object by any class.
In general pass is used when you introduce a new block and want to leave it empty:
expression:
pass
You must include at least one instruction inside a block, that's why sometimes you need pass to say that you don't want to do anything inside the block. It is true for functions:
def do_nothing():
pass # function that does nothing
loops:
for i in collection: # just walk through the collection
pass # but do nothing at each iteration
exception handling:
try:
do_something()
except SomeException:
pass # silently ignore SomeException
context managers:
with open(filename): # open a file but do nothing with it
pass

The pass statement means that you initialise your class without defining a constructor or any attributes. Try ommitting it : The error that you see is due to the fact that python will expect the following line to belong to your class - and will consider that the indentation used is not correct.
Regarding the fact that your class name is called again inside your function : it means that you are instanciating the class you just defined. Thus, what your function returns is an object of your class.

Related

Is there a way to mock the return for type(), without replacing with isinstance()?

I am trying to unit test a block of code, and I'm running into issues with mocking the object's type to grab the right function from a dictionary.
For example:
my_func_dict = {
Foo: foo_func,
Bar: bar_func
FooBar: foobar_func
}
def generic_type_func(my_obj):
my_func = my_func_dict[type(my_obj)]
my_func()
With this code, I can swap between functions with a key lookup, and it's pretty efficient.
When I try to mock my_obj like this, I get a KeyError:
mock_obj = Mock(spec=Foo)
generic_type_func(mock_obj)
# OUTPUT:
# KeyError: <class 'unittest.mock.Mock'>
Because it's a mock type. Although, when I check isinstance(), it returns true:
is_instance_Foo = isinstance(mock_obj, Foo)
print(is_instance_foo)
# Output:
# True
Is there any way to retain the type() check, and using the dictionary lookup via a key, while still maintaining the ability to mock the input and return_type? Or perhaps a different pattern where I can retain the performance of a dictionary, but use isinstance() instead so I can mock the parameter? Looping over a list to check the type against every possible value is not preferred.
I managed to unit test this by moving the function to the parameter itself, and implicitly calling the function from the parent. I wanted to avoid this, because now the function manipulates the parent implicitly instead of explicitly from the parent itself. It looks like this now:
def generic_type_func(self, my_obj):
my_obj.my_func(self)
The function then modifies self as needed, but implicitly instead of an explicit function on the parent class.
This:
def my_func(self, parent):
self.foo_prop = parent
Rather than:
def my_foo_func(self, foo):
foo.foo_prop = self
This works fine with a mock, and I can mock that function easily. I've just hidden some of the functionality, and edit properties on the parent implicitly instead of explicitly from within the class I'm working in. Maybe this is preferable anyways, and it looks cleaner with less code on the parent class. Every instance must have my_func this way, which is enforced via an abstract base class.

Get owner instance of attribute

I want to get the instance handle of an attribute when this attribute is passed to a function without its instance. To make it more clear see the example code below:
class aClass():
def __init__(self):
self.anInstanceAttribute = 'ok'
def aFunction(anInstanceAttribute):
print(anInstanceAttribute)
#how to get the instance handle ('the self') of the anInstanceAttribute?
a = aClass()
aFunction(a.anInstanceAttribute)
This is not possible without introspection/frame hacks.
aFunction(a.anInstanceAttribute)
The function arguments are fully evaluated before calling the function. So, the function receives the string object "ok" and knows nothing about the instance a. If you want the function to know something about the instance, then pass in a instead.

What is the use of class attribute which is a method/function

In Python when we define class all its members including variables and methods also becomes attributes of that class. In following example MyClass1.a and MyClass1.mydef1 are attributes of class MyClass1.
class MyClass1:
a = 10
def mydef1(self):
return 0
ins1 = MyClass1() # create instance
print(MyClass1.a) # access class attribute which is class variable
print(MyClass1.mydef1) # No idea what to do with it so just printing
print(ins1.mydef1) # No idea what to do with it so just printing
Output
10
<function MyClass1.mydef1 at 0x0000000002122EA0>
<bound method MyClass1.mydef1 of <__main__.MyClass1 object at 0x000000000212D0F0>>
Here attribute a is a variable and it can be used like any other variable.
But mydef1 is a method, if it is not invoked and just used like MyClass1.mydef1 or ins1.mydef1, it returns object for that method(correct me if I am wrong).
So my question is, what can we do with the Class/instance methods without invoking it? Are there any use cases for it or is it just good to know thing?
An attribute of a class that happens to be a function becomes a method for instances or that class:
inst.foo(params, ...)
is internally translated into:
cls.foo(inst, params, ...)
That means that what is actually invoked is the attribute from the class of the instance, and the instance itself is prepended to the argument list. It is just Python syntax to invoke methods on objects.
In your example the correct uses would be:
print(MyClass1.mydef1(ins1)) # prints 0
print(ins1.mydef1()) # also prints 0
Well instance methods can be called with the appropriate parameters of course:
print(ins1.mydef1()) # no parameters, so empty parenthesis, this call should print "0" in your example instead of the method description
If you use it without the parenthesis, you are playing with reference to the function, I don't think you can have any use of it, except checking the list of methods available in a class or something like that.

Should I decorate a function?

Trying to determine if I should try to use decorator or some other Pythonic way to reduce code that many of my functions are doing. I would like these functions to be able to call just maybe one other function at the start of each function or somehow "decorate" the start of each function. I have never used decorator before and am struggling to implement this decorate idea in a pythonic way to reduce the common set of share code at each function.
I have many functions that will perform the same set of steps at the start of the function. However, there is some structure concerns of the common code that makes this "decorator" idea difficult :
The functions are all in child class of a parent class.
The common commands between the functions reference variable names
that are specific to the function (but a subset of the function
name).
The common commands need to return to the caller and not execute any
more of the child function if a certain condition is met. ("if jobj : " block in the sample code)
For variable/attribute examples, child function get_nas_server(self) will utilize "nas_server" variable variants in the common set of code. Subtracting the get_ from the function name reveals the base of the variable name to be used in the common set of code. Example variables names and object attributes derived from "get_nas_server" function name:
nas_server
nas_server.json
self.nas_server (attribute)
Here is the common code from one of the functions:
####################################################################
def get_nas_server(self):
####################################################################
"""\nGets COMMAND nas_server and places data into self.nas_server"""
try:
self.nas_server
return self.nas_server
except AttributeError:
pass
self.get_file_cmd('nas_server')
jobj = self.fresh_json('nas_server.json')
if jobj :
self.nas_server = jobj
return self.nas_server
self.get_file_cmd('get_nas_server')
Everything below that code above in the function is specific to the function purpose and not appropriate for discussion here. Basically I am trying to make all that code above reusable in my functions, but the code has to have the variables and attribute changed depending on the function name.
Thanks for reading if you got this far and thanks for all help.
Seems like something you could define as a helper method in the parent class:
class Parent(object):
def _get_something(name):
try:
return getattr(self, name)
except AttributeError:
pass
self.get_file_cmd(name)
jobj = self.fresh_json(name+'.json')
if jobj :
setattr(self, name, jobj)
return jobj
self.get_file_cmd('get_'+name)
As this snippet demonstrates, you can use the getattr(), setattr() and hasattr() functions to reference object attributes by name.
You can use a decorator inside your class, if the initial bookkeeping stuff is too specific to that class. Everytime you need to do that initial check inside a class method, you can simply decorate it with the auto_nas decorator I have added below. The scope of this wrapper, I am assuming, is specific to this class alone. Otherwise, you can move it outside the class for generality, but remember to change (self=None) if you're going to do so.
class YourMainClass():
# This is your main class inside which all the methods are defined.
def auto_nas(func):
# This wrapper function will be called instead of your class methods.
def wrap(self):
# All your bookkeeping stuff goes here.
try:
self.nas_server
return self.nas_server
except AttributeError:
pass
self.get_file_cmd('nas_server')
jobj = self.fresh_json('nas_server.json')
if jobj :
self.nas_server = jobj
return self.nas_server
self.get_file_cmd('get_nas_server')
# Things went well - we shall call the actual method.
return func(self)
return wrap
#auto_nas
def get_nas_server(self):
# This is one of your methods that require bookkeeping
pass
Also, notice the self inside the wrapper function. It is automatically passed as an argument by Python, and thus you can access all the instance specific attributes from inside that decorator. Once again, this is appropriate if your decorator must do jobs specific to each instances of your class. If that is not the case, you can simply put all of that code in a function and call it each time whenever you want.
Much thanks to Augurar for pointing in the proper direction. I ended up created a stub method in the parent class. Just needed to call the method with the proper technique to "extend" the parent method. Then calling that stub method from the child class with super() There must be a proper name for this technique? method override? method extend?
Here is the parent class method mostly as Augurar suggested:
###########################################################################
def get_stub(self,fcmd):
###########################################################################
try:
return getattr(self, fcmd)
except AttributeError:
pass
jobj = self.fresh_json(fcmd + '.json')
if jobj :
setattr(self, fcmd, jobj)
return jobj
if not self.get_file_cmd(fcmd):
self.log.error("{} not found".format(fcmd))
return False
Here is the manner in which the child method uses this parent method:
####################################################################
def get_nas_server(self):
####################################################################
super().get_stub('nas_server')
#bunch of child method specific code below here

PYTHON: AttributeError - calling function in a member function of a class

I'm having trouble with classes in Python 2.7:
First, I really do not know how to use the __init__ properly, so I have just used a dummy call to print. What should I do instead?
Second, I would like the member function readAnyFormat to call a few functions (later I will create a kind of case statement). My attempt produced an AttributeError. How do I do this correctly?
My class is as follows:
class ArangeData:
def __init__(
self):
print ' '
def readAnyFormat(
self,
config = True,
mypath='text.txt',
data_format='ASCII',
data_shape='shaped'):
#Here the function should be called:'
#NOT WORKING:
#AttributeError: ArangeData instance has no attribute 'readASCII'
if data_format=='HDF5':
readHDF5()
elif data_format=='ASCII':
readASCII()
def readASCII():
'doing stuff in here'
def readHDF5():
'doing other stuff in here, which is not the business of readASCII'
def otherMemberFunction(self):
'do not care what they are doing above!'
You should move the definition of readASCII and readHDF5 so they are above the two if statements.
You don't need to have the dummy print statement in __init__. If you have nothing to initialize you can simply use pass, or better yet as #chepner commented don't even define __init__.

Categories