Can staticmethod be imported? - python

there are many examples of staticmethod in a class with caller in one file. this works fine. but i have tried to save the class with staticmethod in a single file and import it from caller. this then throws the error "AttributeError: 'module' object has no attribute methodname"
i am using python2.7.
used exact example from Static methods in Python?
import MyClass
# belwo class is saved in a saparate file named MyClass.py
# class MyClass(object):
# #staticmethod
# def the_static_method(x):
# print(x)
MyClass.the_static_method(2) # outputs 2
# if via import, we have the error: AttributeError: 'module' object has no attribute 'the_static_method'

In your example, since the name of the python file (MyClass.py) is the same as the class name, Python will assume you are referring to the module MyClass(which is your file) instead of the class MyClass. One suggestion is to change your first line import MyClass to from MyClass import MyClass. Then it should work. It's generally better to follow the Python naming convention recommended here https://softwareengineering.stackexchange.com/questions/308972/python-file-naming-convention

Related

How to prevent Python class instance variable typo?

A python class function had something like this:
class Widget:
def __init__(self):
self.foo_bar = 0
def fun(self, xyz):
self.foobar = xyz
A typo. The code for fun() should have referenced self.foo_bar. This took surprisingly long to debug (as the actual functions were more complex).
Is there a way to enforce that class instance variables can only be introduced (declared) in __init__? Python happily created a new class instance variable instead of generating an error. An error would have saved a lot of time.
If I run pylint on this code, I get the following errors:
test.py:1:0: C0114: Missing module docstring (missing-module-docstring)
test.py:1:0: C0115: Missing class docstring (missing-class-docstring)
test.py:5:4: C0116: Missing function or method docstring (missing-function-docstring)
test.py:6:8: W0201: Attribute 'foobar' defined outside __init__ (attribute-defined-outside-init)
test.py:1:0: R0903: Too few public methods (1/2) (too-few-public-methods)
You can configure pylint to disable the warnings you might not care as much about, e.g. missing-module-docstring, but the one that catches your attribute typo is this one:
test.py:6:8: W0201: Attribute 'foobar' defined outside __init__ (attribute-defined-outside-init)

Class Identification in dynamically loaded classes v.s. classes loaded by import

Here's the minimal reproduction for something I'm working on. This is using Python 3.6.5:
sample.py:
import importlib.util
import inspect
from test import Test
t = Test()
spec = importlib.util.spec_from_file_location('test', './test.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
loaded_test = None
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj):
loaded_test = obj
print(type(t))
print(loaded_test)
print(isinstance(t, loaded_test))
print(issubclass(t.__class__, loaded_test))
test.py (in the same directory):
class Test(object):
pass
Running this code will give you the following output:
<class 'test.Test'>
<class 'test.Test'>
False
False
So why is the object that we load using importlib, which is identified as 'test.Test', not an instance or subclass of the 'test.Test' class I created using import? Is there a way to programmatically check if they're the same class, or is it impossible because the context of their instantiation is different?
Why is the object that we load using importlib, which is identified as test.Test, not an instance or subclass of the test.Test class I created using import?
A class is "just" an instance of a metaclass. The import system generally prevents class objects from being instantiated more than once: classes are usually defined at a module scope, and if a module has already been imported the existing module is just reused for subsequent import statements. So, different references to the same class all end up pointing to an identical class object living at the same memory location.
By using exec_module you prevented this "cache hit" in sys.modules, forcing the class declaration to be executed again, and a new class object to be created in memory.
issubclass is not doing anything clever like a deep inspection of the class source code, it's more or less just looking for identity (CPython's implementation here, with a fast-track for exact match and some complications for supporting ABCs)
Is there a way to programmatically check if they're the same class, or is it impossible because the context of their instantiation is different?
They are not the same class. Although the source code is identical, they exist in different memory locations. You don't need the complications of exec_module to see this, by the way, there are simpler ways to force recreation of the "same" class:
>>> import test
>>> t = test.Test()
>>> isinstance(t, test.Test)
True
>>> del sys.modules['test']
>>> import test
>>> isinstance(t, test.Test)
False
Or, define the class in a function block and return it from the function call. Or, create classes from the same source code by using the three-argument version of type(name, bases, dict). The isinstance check (CPython implementation here) is simple and will not detect these misdirections.

How to access class module from object instance?

I want to access module-level variables of the module that defines the class the instance is derived from. I only have the instance to work from. I tried self.__class__.__module__[<some var>] but unlike the __class__ attribute which returns the class object, __module__ just returns a string name, not the module object itself. How can I get the module object in this situation?
The __module__ attribute can be used as a key in the sys.modules dictionary:
import sys
class_module = sys.modules[instance.__class__.__module__]

When does a passed class instance require an import in python

So I have a python 2.7 project with three modules. Two contain classes and one is a script. An example files structure is shown below
project/
__main__.py
__init__.py
- serial_connect/
ser_conn.py
__init__.py
- ui/
parse_file.py
__init__.py
ser_conn.py contains a class which handles all interaction with some RS-232 hardware device. It contains methods such as open(), close(), send_go() just basically everything required for this connection.
parse_file.py contains a class which has methods relating to parsing a file and getting text commands which are associated with serial commands.
e.g. if the text file contains the command "send_go" parse_file.py will parse this command and call Ser_Conn.send_go()
__main.py__ contains the main() function. in main() an instance of the Ser_Conn class is created and then passed to the Parse_File class as there exists only one instance of a serial connection in the program and it is required by both main() and the Parse_File class.
My question is as follows
In methods of Parse_File I call methods of the Ser_Conn instance, such as Ser_Conn.send_go() but parse_file.py does not complain about there being no
from serial_connect.ser_conn import Ser_Conn
There only exists a ser_conn import in __main__.py. why does this work?
In python, an instance carries all the "stuff" that it needs to do it's work along with it. At a high level, (and somewhat simplified) when you write:
qux.whatever
python looks at the object qux and then finds its whatever attribute (if it has one). Note that python doesn't care what type qux is, only that it has a whatever attribute. I could create multiple objects that satisfy this interface:
class Foo(object):
whatever = 'Hey Dawg!'
class Bar(object):
whatever = 'I satisfy the interface too!'
Also note that these objects could be defined anywhere. As long as you manage to get a reference to the object (e.g. it was passed into a function) you can use the object with all of it's attributes and methods.
maybe a more concrete example would help -- Say you have 4 modules, foo, bar, call_method and driver. foo, bar and call_method don't know anything about each other, but driver imports the other 3. Then you can do something like this:
# foo.py
class Foo(object):
def method(self):
return 'foo!'
# bar.py
class Bar(object):
def method(self):
return 'bar!'
# call_method.py
def go(object_with_method):
print(object_with_method.method())
# driver.py
import call_method
import foo
import bar
call_method.go(Foo()) # call the method on a foo instance
call_method.go(Bar()) # call the method on a bar instance
You're passing the connection instance to parse_file which means Python already knows the class and other details of that object. So that's why you don't need to import the class again in the parse_file code.
You only need to import something if you wish to use that something in that file.
When you created the object Python used the class to construct the object and that's sufficient. You can of course add that import line in parse_file but only if you actually need to use the class in that file (otherwise the import line it's very useful).

How does Python handle imported subclasses?

I am working on a project that requires me to build several classes and subclasses in one file, and use them in a second file. I would like to ask how Python handles importing the first file into the second.
For instance, if i have a file my_classes.py:
class Myclass(object):
pass
class Mysubclass(myclass):
pass
will using the following code work:
from my_classes import Myclass
print Mysubclass
(where the print command is just an example of using Mysubclass), or do I need to import Mysubclass explicitly?
Thanks in advance!
This won't work. Python import statement doesn't care about subclasses. Actually, it doesn't care about anything. It does precisely what you tell it to do. "Explicit is better than implicit" is a popular saying in Python circles.
Here:
from my_classes import Myclass
You told Python to import only Myclass.
This will import both classes:
from my_classes import Myclass, Mysubclass
You can read how Python import works here.
Your subclass will not be available if you do it like this. You must import every object by itself.
Here a quick example
test_class.py
class MyClass(object):
def init(self):
print self.class
class MySubClass(MyClass):
def __init__(self):
print self.__class__
test_class_import.py
from test_class import MyClass
MyClass()
MySubClass()
##output##
<class 'test_class.MyClass'>
Traceback (most recent call last):
File "test_class2.py", line 4, in <module>
MySubClass()
NameError: name 'MySubClass' is not defined
but
from test_class import MyClass, MySubClass
MyClass()
MySubClass()
##output##
<class 'test_class.MyClass'>
<class 'test_class.MySubClass'>
Every module has a namespace.
A namespace is a mapping from variable names to values (Python objects).
The statement
import my_classes
makes the my_classes namespace accessible from the current module by placing the variable name my_classes in the current module's namespace. You can then access values from my_classes with the syntax
my_classes.variable
So, for example:
import my_classes
print my_classes.Mysubclass
print my_classes.MyClass
If that is too much typing, I suggest
import my_classes as MC
print MC.Mysubclass
print MC.MyClass
you could also do
from my_classes import Mysubclass, MyClass
but this form of import is discouraged by some Python experts.
from my_classes import Mysubclass, MyClass
loads the entire module my_class but only
places the variable names Mysubclass and MyClass in the current module's namespace. They point to the same values as do the variables of the same name in the my_classes namespace. You don't get access to anything else from the my_class module's namespace.

Categories

Resources