Why does this class run? - python

I've been playing with my codes a little for a while, and this one is not about a bug or anything, but i just don't understand why class main() runs without needing to initialize it...
class vars():
var1 = "Universe!"
var2 = "Oscar!"
var3 = "Rainbow!"
class main():
print (vars.var1)
def __init__(self):
print (vars.var2)
print (vars.var3)
But yes, thank you very much for reading.

Unlike many other languages, class body is an executable statement in Python and is executed immediately as the interpreter reaches the class line. When you run this "program":
class Foo:
print("hey")
it just prints "hey" without any Foo object being created.
The same applies to the function definition statement def (but not to function bodies). When you run this:
def foo(arg=print("hi")):
print("not yet")
it prints "hi", but not "not yet".

When a class is created, Python executes all of the code directly inside the class declaration in a new namespace. This is so that any variables created in the class (most commonly methods, created by ordinary function declarations like def foo(self...)) are attached to the class rather than being global.
But the code still runs immediately. If it calls print() or does something else which creates a visible side effect, that will happen now, not when the class is instantiated (called to create a new instance). If you need something to happen when the class is instantiated, write an __init__() method instead.

main is a class not a function. Thus the code contained in the class declaration runs immediately because all statements are executed as they appear in code. As a method declaration is reached, it's bound to the class as a member, so in a way methods execute as well but are not called.

When Python read your code, it looked into class vars and defined all the variables. Then, it went into class main and executed the code there, as well as defining init. Python just executes whatever which is not in a function definition.

Related

Calling functions from different Classes in Python

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.

Why is a method of a Python class declared without "self" and without decorators not raising an exception?

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)

Python decorator function called at compile time

I hope that someone familiar with Python's compilation / run-time procedures could shed some light on my question relating to how Python compiles decorator functions.
Within my sample code, I've included a testing print statement in the "writeit" decorator just before the logtofile closure is defined. If you run the entire code that I've provided, the "testing" print statement in writeit is called for each #writeit decorator defined in the Customer class-- before writeit is ever used.
Why is logtofile being called at compile time? Could someone please explain this behavior?
def writeit(func):
print('testing')
def logtofile(customer, *arg, **kwargs):
print('logtofile')
result = func(customer, *arg, **kwargs)
with open('dictlog.txt','w') as myfile:
myfile.write(func.__name__)
return result
return logtofile
class Customer(object):
def __init__(self,firstname,lastname,address,city,state,zipcode):
self._custinfo = dict(firstname=firstname,lastname=lastname,address=address,city=city,state=state,zipcode=zipcode)
#writeit
def setFirstName(self,firstname):
print('setFirstName')
self._custinfo['firstname']=firstname
#writeit
def setLastName(self,lastname):
print('setLastName')
self._custinfo['lastname']=lastname
#writeit
def setAddress(self,address):
print('setAddress')
self._custinfo['address']=address
def main():
cust1 = Customer('Joe','Shmoe','123 Washington','Washington DC','DC','12345')
cust1.setFirstName('Joseph')
cust1.setLastName('Shmoestein')
if(__name__ == '__main__'): main()
Your code runs when the module is imported. Python executes all top-level statements, including class definitions at that time.
A class definition body is executed as a function, with the local namespace becoming the class attributes. This means that class bodies are executed on import, provided the class is defined at the top-level of the module.
When Python encounters a decorated function when executing, it'll define the class, then execute the decorator function, passing in the function object and binding the return value of the decorator to the name of the function. Since the class body is executed during import, this means your decorator is executed at that time.
There is no compile time. A def statement, and the associated decorator calls are executable statements.
Accordingly, when Python loads a module, it executes the statements in order. When executing a class statement, one of the early stages is executing all of the statements in the class body. As part of that defs are run to create functions, and those function objects will be passed to decorators for processing.
Your "testing" print statement will run whenever the decorator is called, not when the function it returns is called. If you want that behaviour, move the decorator into the inner function.

Why does a class get "called" when not initiated? - Python

For example, in the following code:
class test:
print "Hi"
Python would automatically print 'hi'. Sorry if this is an obvious question, but I can't find out why Python would do that unless a 'test' object was initiated.
* I just started programming in general a few months ago and Python is my first language, so please spare some mercy on me.
You are building a class; the body of a class is executed as a function to build the definition. The local namespace of that 'function' forms the set of attributes that make up the class. See the class statement documentation.
Methods in the class body are not executed; like function definitions, you need to call them first. But if you didn't first call the class body, you don't know what methods the class has, at all.
In the same way, any top-level code in a module is executed when you import a module, to form the module namespace. If you put print "Hi" in a module, it is also executed immediately.

importing without executing the class - python

my problem is about i have a file that contain class and inside this class there is bunch of code will be executed
so whenever i import that file it will executed ! without creating an object of the class ! , here is the example
FILE X
class d:
def __init__(self):
print 'print this will NOT be printed'
print "this will be printed"
file B
import x
output is this will be printed, so my question is how to skip executing it until creating a new object?
You can't do that in Python, in Python every class is a first level object, a Python class is an object too and an class attribute can exist even if there is no instances of that class. If you just want to suppress the output of the print statement you can redirect the output of your print statements on the importing moment or create a context like the one provided in this first answer and use the __import__ statement manually.
If all you want to do is suppress the print (or any other executable statements) during import, surround them with a check for top module execution:
if __name__ == '__main__':
print 'this will be printed'
This will prevent the print during import, but allow it when the module is
executed interactively.
As others have pointed out, the second print statment is executing because it's one of the suite of statements making up the class declaration -- all of which are executed when the module they're in is imported because the declaration is part of its top-level code verses it being nested inside a function or method.
The first print statement isn't executed because it's part of a method definition, whose statements don't execute until it's called --- unlike those within a class definition. Typically a class's __init__() method is called indirectly when an instance of the class is created using the class's name, which would be d() for one named d like yours.
So, although it contradicts what's in the text of the strings being displayed, to make that second print statement only execute when instances of the class are created (just like with the first one) you'd need to also make it part of the same method (or called by it). In other words, after doing so, neither of them will execute when the file the class is in is imported, but both will when any instances of the class are created. Here's what I mean:
File x.py:
class d:
def __init__(self):
print 'print this will NOT be printed' # not true
print "this will be printed when object is created"
File b.py:
import x # no print statements execute
obj = d() # both print statements will be executed now
Your question is like: I have a function
def f():
print(1)
print(2)
How do I make print(1) executed, but not print(2)? There is really no easy way. What you have to understand is that def __init__(self) is also a statement. Your class consists of that statement and print statement. There is no easy way to execute one but not the other. Of course, if you can change the source of the class, just put the print inside __init__, where it will be called after instance creation.
(Copied from a comment above in case it is useful to future readers)
Agree with #mgilson and #EmmettJButler - this code is likely best-placed in the __init__. When Python imports a module, it executes the module-level code, including building the class definition with the class methods, etc. Therefore when you import X, and class d's definition gets built (so you can call it from B), it executes the code inside of the class. Usually this means you'll have class-level variables set and unbound methods ready to be attached to instances, but in your case it means that your statement will be printed.
As suggested by the others, refactoring the code is likely your best bet.

Categories