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__.
Related
I'm relatively new in python and I have the following question, my code looks something like this:
class Hkprop:
def hkprop_f(self):
hkprop= self.Mkprop().fun2() + self.Fkprop().fun4()
return hkprop
class Fkprop:
def fun1(self):
#something
def fun2(self):
self.fun1()
class Mkprop:
def fun3(self):
#something
def fun4(self):
self.fun1() #here I want to call fun1 but I don't know if it is possible or how to do it
I know this might be a super basic question, but if someone could help me I would really appreaciate it. I've been looking and came across #staticmethod, but I didn't completely understand. Is there a way of calling the function without using it?
If you want to call fun1, you can do Hkprop.Fkprop.fun1()
Yes, this is basic but sometimes, even such basic questions takes a little time to figure it out. So, I am assuming that your indentations are correct, and you have nested classes. Here is the solution that I did.... Hope this is helpful to you...
You will need to use the class inheritance methodolody, or simply learn how to instantiate class objects from one class to another as shown below.
When you save this code to a file a run it. You will see that first it will instantiate Hkprop.Mkprop and the call fun4. The next thing, we have done is instantiate Hkprop.Fkprop in func4 to be able to call func1 in FKprop class.
class Hkprop:
def hkprop_f(self):
hkprop= self.Mkprop().fun2() + self.Fkprop().fun4()
return hkprop
class Fkprop:
def fun1(self):
print('I just called this function')
def fun2(self):
self.fun1()
class Mkprop:
def fun3(self):
print('this is soemthing')
def fun4(self):
fk = Hkprop.Fkprop()
fk.fun1()
if __name__ == '__main__':
mk = Hkprop.Mkprop()
mk.fun4()
Let's breakdown your code. You wrote:
def fun4(self):
self.fun1()
There are 2 problems here.
self represents the instance of the class. Since, Mkprop class has no defintion of fun1() so it cannot access fun1()
fun1() function also expects a parameter in Fkprop class
In fun4, if you want to call fun1() then make the following change:
def fun4(self):
Hkprop.Fkprop.fun1(self)
Moreover, in python, functions cannot have empty body. Your current code will get the error:
IndentationError: expected an indented block
Because the interpreter expects a function body that is indented. To keep the empty functions, change fun1 & fun3 functions like this
def fun1():
pass
def fun3():
pass
pass is a special statement in Python that does nothing. It only works as a dummy statement.
I never tried nested classes before. In your case, it seems like you're calling a nonexistent function from a class. fun1() does not exist in class Mkprop.
If you want to call fun1(), you have to call it from it's respective class, therefore, Hkprop().Fkprop().fun1(). It goes something like this: Parent Class -> Sub class -> Function.
I thought that the following code would result in an error because as far as I have read, a method in a Python class must either have "self" (or any other label, but "self" by convention) as its first argument, or "cls" or similar if the #classmethod decorator is used, or none if the #staticmethod decorator is used.
How come I get no error running this with Python 3.5 in the Terminal, even though test_method does not meet these requirements? It seems to work fine as a static method, but without the decorator.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
def test_method(args):
print(args[1])
#staticmethod
def static_method():
print("static_method")
#classmethod
def class_method(cls):
print("class_method")
def main(args):
MyClass.test_method(args)
if __name__ == '__main__':
sys.exit(main(sys.argv))
Output:
$ python3 testscript.py "testing"
$ testing
EDIT:
My question could also be phrased differently, drawing attention away from self and to #staticmethod: "How come I'm getting a seemingly working static method without the #staticmethod decorator?"
In Python 2, functions defined in a class body are automatically converted to "unbound methods", and cannot be called directly without a staticmethod decorator. In Python 3, this concept was removed; MyClass.text_method is a simple function that lives inside the MyClass namespace, and can be called directly.
The main reason to still use staticmethod in Python 3 is if you also want to call the method on an instance. If you don't use the decorator, the method will always be passed the instance as the first parameter, causing a TypeError.
There is nothing special about this. In python 3 there is no difference between a function defined inside a class or a function defined outside a class. Both of them are normal functions.
The self that you are talking about here or maybe cls comes into picture only when you access the function through an instance. Hence here you didn't get any error.
However if you modify your code just a little bit to look like the following, then you'd get an error that you expected.
def main(args):
MyClass().test_method(args)
# Should throw an error
EDIT:
#staticmethod will work on both class instances like MyClass().test_method(args)and just a regular direct call like MyClass.test_method(args)
However a regular method(without self in it) can't be called on a class instance. So you will always have to call it as MyClass.test_method(args)
self isn't necessarily required. However, if you want to reference any variable or value that is associated with the object(instantiation of the class) (E.g. for a class about cars, it's speed, self.speed) you'll need to have self as a parameter in the function. For this reason, it's common practice to always have self as an argument, otherwise you aren't really using the class for the right reason.
EDIT:
This will actually throw an error if you do the following:
class a():
def __init__(self, x):
self.asd = x
def hello(x):
print(x)
>>> g = a(4)
>>> g.hello(5)
as when calling "hello", both "self" and "4" will be passed as parameters. It would work in the following instance, which is what I was saying above:
>>> g = a
>>> g.hello(4)
or
>>> a.hello(4)
To add on to the existing answers here and provide a code example:
class MyClass:
def __init__(self):
pass
def myStaticMethod():
print("a static method")
#staticmethod
def myStaticMethodWithArg(my_arg):
print(my_arg)
print("a static method")
MyClass.myStaticMethod()
MyClass.myStaticMethodWithArg("skhsdkj")
abc = MyClass()
abc.myStaticMethodWithArg("avc")
Try removing the #staticmethod decorator and rerunning the code and see what happens! (The very last call will fail since the method is passed in both self and the string input. By adding the decorator, we can guide the interpreter to perform our desired action)
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.
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
I am trying to learn about classes, can someone explain to me why this code is not working. I thought when calling a function from a class, "self" is automatically ommitted, but the interpreter tells me that argument "a" is missing (he thinks self = 10).
#! coding=utf-8
class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
d = test.do
print(d(10))
Instantiate the class first:
d = test().do
print(d(10)) # prints 100
test.do is an unbound method, test().do is bound. The difference is explained in this thread: Class method differences in Python: bound, unbound and static.
You have to instantiate the class first:
d = test()
then you can call a method:
print(d.do(10))
if you want to use method statically you have to declare it in python
#! coding=utf-8
class test:
def __init__(self):
"do something here"
#staticmethod
def do(a):
return a**2
d = test.do
print(d(10)) #and that's work
Since you haven't instantiated the class (a fancy term for created) you can't be assigning methods to any random variable. Like already said, you must create the object first, whilst making sure the method you call is a part of the class you called or connected to the class in some way (such as creating another class and then communicating that class with the current class). So you should first type d=test() followed by d.do().
Also, remember that in your declaration of the method you crated a parameter so what you done was wrong in itself anyway, because when you declared the do function, you should have put within the brackets the number you wanted to send to the method to calculate its square. So you type test.do(10) and then the 10 is sent by the self reference to the method to be done whatever it is you told it to do.
One more thing: although it isn't a huge deal, it helps if all of your class names begin with a capital letter, as this is usually the 'pythonic' way to do things, and it also makes your code much easier to read, because when you first called the class, somebody could easily mistaken it for an ordinary function
class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
def __call__(self,a):
return self.do(a)
a = test
test.do(a,10)
#or
a = test().do
a(10)
#or
a = test()
test.do(a,10)
#or
a = test()
print(a(10))