I am playing around with python's namespacing and I have come across some behaviour I can't explain. In particular I wanted to see if you can stop classes being imported with a command like 'from module import *'. In one module, call it moduleA, I have the following:
class __hi(object): pass
class hey(object):
def __init__(self):
# self.hey = __hi()
Then in another module, say moduleB, I import 'everything' from moduleA with
from moduleA import *
This has the desired effect of importing the class 'hey' but not the class __hi.
Now when the line above '# self.hey = __hi()' is uncommented I get an error I don't understand:
"NameError: global name '_hey__hi' is not defined"
It looks as though python has mangled the variable name because the class name has a double underscore. Can anyone explain this?
This question is completely different from that which is referenced. In the linked post presented the name is mangled with the class variable in which the mangled variable is living. That is not what I am asking about.
Edit:
Thanks to vaultah for pointing out that: It doesnt matter where the double-underscore is in the line it will still trigger name-mangling - but could anyone explain why this is the case? It means that, in (highly contrived) situations like the one above, you can never save an instance of a class in another class.
The problem occurs because double underscores are mangled when they are encountered inside a class.
Your class hey includes the line self.hey = __hi(), and because it is within a class the __hi gets mangled to _hey__hi, which fails.
You could solve this by replacing __hi with single-underscore _hi, or removing the underscores, or any of a number of other ways. You could declare your helper class within a block that exits and destroys the name before the file is finished parsing:
def create_hey():
class __hi:
pass
x = __hi
class hey:
def __init__():
self.__hi = x()
return hey
hey = create_hey()
Realistically, though, that's a lot of work. You're better off as numerous commenters have suggested, simply defining __all__ so as to control what may be imported:
__all__ = [ 'hey' ]
Related
I'm new to python. This is not my actual case, it's just my curiosity about importing nested class.
So I have a main.py and test.py.
test.py:
class one():
class two():
def twodef():
pass
so in my main.py, I can do 'import test' or 'from test import one'. But I got error when do: 'from test.one import two'.
error : ImportError: No module named one
Anyone can explain this?
You can only do from module import name for names that exist in the module's global scope - basically, names that are defined in top-level module code. Names that are defined in lower-level scopes - for example within classes as in your example - are not importable. You need to import the object that contains the name, and access it from there.
from test import one
my_two = one.two()
You could do the following:
from test import one
two_object = one.two()
two_object.twodef()
inside test.py
class One:
class Two:
#staticmethod
def twodef():
print("twodef")
My main logic:
from test import One
two_obj = One.Two
two_obj.twodef()
Remove the parenthesis at the end of class definition.
Coding standards:
Always declare your class names in upper camel case (class one => class One).
For more about scope
Preference:
And if you have a single class inside python file, always name that file in that class name but in lower camel case. (test.py => one.py). I have thought this as a standard earlier, but seems its practiced widely. I would use this because, if then project size grew and if you end up having a lot of classes and modules, it's logical and easy to access, rather than visiting the module to find the class name.
Ref1
Ref2
As you know, when the project's code is very large and there are so many attributes and functions defined in a Class, but some of them never be called by the instance of the Class, and maybe some of them has been discarded. Here is a example:
class Foo(object):
""""""
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
...
self.y = 25
self.z = 26
def func1(self):
pass
def func2(self):
pass
def func3(self):
pass
...
...
def func100(self):
pass
if __name__ == '__main__':
f = Foo()
f.func1()
f.func2()
print f.a, f.b, f.z
In the above code, the instance f of class Foo just called func1() and func2(). And how to find all the attributes and functions of class that never called by the instance of class.
I have tried compiler module but that could not solve my question. And dir(my_instance) is just print all the functions and attributes defined the the class.
Thanks in advance.
You can try coverage.py. It's not static analysis, but actually runs your code and records which statements are executed, outputting annotated html or txt as you wish (quite nicely formatted as well). You can then look for functions and methods whose bodies are not executed at all.
This still doesn't take care of unused attributes. And I don't know the answer to that. Maybe comment them out one at a time and see if tests still pass...
It's pretty hard to prove something is or is not used in the general case. Python is a dynamic language; if even one bit of code calls into code the static analyzer doesn't fully analyze, it could be accessing the variables mentioned.
The pylint and flake8 tools will tell you about local and global names that aren't defined prior to use (unless you break them by using from x import * style imports), and about imports that are never used (an import that is never used is usually wrong, but even then, it could be an intentional part of the interface, where linters would have to be silenced), but I don't believe they can tell you that a given attribute is never accessed; after all, someone else could import your module and access said attributes.
Use the profile module in the standard library.
python -m cProfile -o output_file myscript.py
Then load the stats file and use print_callees() to get all the functions that were called--during that run of the program.
I don't know of any easy way to find out which attributes are used.
In python one can easily refer to a global method by means of it's name.
def globalfoo(a):
print(a)
class myClass:
def test(self):
v = globalfoo
v("hey")
t = myClass()
t.test()
Now in python one can also "hide" a (class) method by prefixing it with two underscores. - And I thought(!) one could do the same for global functions - to make a global function module-only. (Similar to C++ where one can decide to put a function declaration not in the header so it's only visible to the current compilation unit).
I then tried to combine this:
def __globalfoo(a):
print(a)
class myClass:
def test(self):
v = __globalfoo
v("hey")
t = myClass()
t.test()
However this doesn't seem to work, an error is thrown that "_myCLass__globalfoo" is undefined. So how would I make both things work: having a reference to a function. And hiding the function from the external scope?
Is a static method in this case the only/best solution?
And I thought(!) one could do the same for global functions - to make a global function module-only.
You were incorrect. Using a double-underscore name for a module-level function will not prevent it from being used in other modules. Someone can still do import yourmodule and then call yourmodule.__globalfoo.
The double-underscore name mangling behavior is defined in the docs:
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
It is purely a textual substitution and takes no account of what (if anything) the double-underscore name refers to. It just takes any identifier occurring anywhere inside the class definition that looks like __blah and changes it to _class__blah. It is specific to class definitions and does not occur for module-level functions.
The best thing to do is prefix your function with a single underscore and document that it is not part of the public API and users of the module should not rely on it. There is nothing to be gained by attempting to "enforce" this privacy.
In python, generally, we don't try that hard to make things inaccessible for other things. We trust other developers' not to modify and access things they shouldn't. Anyway, the way the language works it is almost impossible to make those things completely inaccessible.
What you can do is two things. The standard sign of internal functions in modules is a single underscore - and other programmers should know not to meddle with those functions. Python even supports that convention in some aspect - when importing like this:
from module import *
this won't import underscore-prefixed names.
The other way would be to del method at the end of the module. Not very conventional, but if you must it achieves what you want to do:
def func():
pass
...
...
del func
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.
I've only just dipped my toes into the Python pool. I understand how classes and namespaces interact and del just removes stuff from scope, and all that goodness.
My question is simple. I made a simple "hello world" (Pygame) app, but made a critical mistake (simple case below):
class Cat:
__name = ""
def __init__(self, newName):
__name = newName
def meow(self):
print "Hi from {0}".format(self.__name)
c = Cat("Mittens")
c.meow(); # prints: "Hi from "
In hindsight, my mistake is obvious: in my method (constructor, here specifically) I assigned a value to __name instead of to __self.name (which, by the way, should be mangled and private).
I even understand how and why it works -- it's kind of like static scope in Java/C#.
What I don't understand is how to avoid these kinds of tricksy errors. This was obvious, easy, and the result was, in my case, nothing -- things should have worked but nothing happened.
How do Python developers avoid this problem? Is seems like it would be very common.
In this case, I would definitely avoid adding __name to the class namespace. Since __name is (supposed to be) set by the initializer (__init__) unconditionally, there is no point to having a class level __name.
e.g.:
class Cat:
def __init__(self, newName):
__name = newName
def meow(self):
print "Hi from {0}".format(self.__name)
c = Cat("Mittens")
c.meow() # prints: "Hi from "
Now run the code and you'll get an AttributeError which helps to catch these sorts of bugs.
In other words, the purpose of __init__ in your code is to set __name on the new instance being initialized (self) via self.__name = newName. In your code, you're providing a "safety net" by setting __name on the class. In python, if an attribute isn't found on the instance, it is then looked up on the class. However, this "safety net" is actually a bad thing in this case -- you get different behavior than you expected rather than an Exception which could be used to help you track down the bug.
As a side note, the way attribute access on an instance works (baring interesting things like __getattribute__) is that python first looks on the instance for the attribute, then it searches the class and then it works it's way up the class's method resolution order (which is different for old and new-style classes).
Static analysis tools such as pep8, pylint, pyflakes and flake8 can help to certain extent. For example, pyflakes would complain about your code (placed in a file named stack_overflow-2013-03-08.py):
$ pyflakes stack_overflow-2013-03-08.py
stack_overflow-2013-03-08.py:8: local variable '__name' is assigned to but never used
But nothing beats a good set of tests. Needless to say, if you had a test for Cat.meow that reasonably covered its range of functionality, you would have caught this problem right meow.