All of the tutorials I see online show how to create classes with __init__ constructor methods so one can declare objects of that type, or instances of that class.
How do I create a class (static in Java) so that I can access all methods and attributes of that class without having to create new instances/objects?
For example:
class World:
allElems = []
def addElem(x):
allElems.append(x)
World.addElem(6)
print(World.allElems)
EDIT
class World(object):
allAirports = []
#staticmethod
def initialize():
f = open(os.path.expanduser("~/Desktop/1000airports.csv"))
file_reader = csv.reader(f)
for col in file_reader:
allAirports.append(Airport(col[0],col[2],col[3]))
error: name 'allAirports' is not defined
The Pythonic way to create a static class is simply to declare those methods outside of a class (Java uses classes both for objects and for grouping related functions, but Python modules are sufficient for grouping related functions that do not require any object instance). However, if you insist on making a method at the class level that doesn't require an instance (rather than simply making it a free-standing function in your module), you can do so by using the "#staticmethod" decorator.
That is, the Pythonic way would be:
# My module
elements = []
def add_element(x):
elements.append(x)
But if you want to mirror the structure of Java, you can do:
# My module
class World(object):
elements = []
#staticmethod
def add_element(x):
World.elements.append(x)
You can also do this with #classmethod if you care to know the specific class (which can be handy if you want to allow the static method to be inherited by a class inheriting from this class):
# My module
class World(object):
elements = []
#classmethod
def add_element(cls, x):
cls.elements.append(x)
You could use a classmethod or staticmethod
class Paul(object):
elems = []
#classmethod
def addelem(cls, e):
cls.elems.append(e)
#staticmethod
def addelem2(e):
Paul.elems.append(e)
Paul.addelem(1)
Paul.addelem2(2)
print(Paul.elems)
classmethod has advantage that it would work with sub classes, if you really wanted that functionality.
module is certainly best though.
There are two ways to do that (Python 2.6+):
static method
class Klass(object):
#staticmethod
def static_method():
print "Hello World"
Klass.static_method()
module
your module file, called klass.py
def static_method():
print "Hello World"
your code:
import klass
klass.static_method()
Ancient thread, but one way to make this work is:
class Static:
def __new__(cls):
raise TypeError('Static classes cannot be instantiated')
Then, you can use it like so:
class Foo(Static): ...
Seems the most 'Pythonic' to me, anyway.
Example use case: singleton class where I register handlers for conversion between types.
Cheers!
Seems that you need classmethod:
class World(object):
allAirports = []
#classmethod
def initialize(cls):
if not cls.allAirports:
f = open(os.path.expanduser("~/Desktop/1000airports.csv"))
file_reader = csv.reader(f)
for col in file_reader:
cls.allAirports.append(Airport(col[0],col[2],col[3]))
return cls.allAirports
Related
I am working on an API for my website, I will release the API as a package for Python. How can I make a function not accessible from the class object ? I have tried to use classmethod but it seems not to work, I still can access the function from an outside Python file.
main.py
class MyClass:
def __init__(self):
self.my_var = 5
#classmethod
def dont_access_me(self) -> str:
return 'Dont Access Me'
second.py
from main import MyClass
instance = MyClass()
print(instance.dont_access_me()) # valid
Python does not really have private methods.
What is however common practice is to prefix methods with an underscore if you want to indicate, that users should not use this function and that users cannot expect this function to exist or to have the same signature in a future release of your API.
if you have:
class MyClass:
def __init__(self):
self.my_var = 5
def amethod(self):
rslt = self._dont_access_me()
def _dont_access_me(self) -> str:
return 'Dont Access Me'
instance = MyClass()
then users know, that they can use.
instance.amethod(), but that they should not use instance._dont_access_me()
classmethods are like in most other programming languages something completely different. They are used for methods, that can be called without having an instance,
However they can also be called if you have an instance.
An example would be:
class AClass:
instance_count = 0
def __init__(self):
cls = self.__class__
cls.instance_count += 1
self.idx = cls.instance_count
#classmethod
def statistics(cls):
print("So far %d objects were instantiated" %
cls.instance_count)
a = AClass()
b = AClass()
AClass.statistics()
# However you can also access a classmethod if you have an instance
a.statistics()
You cannot make a class method truly private. There is a good discussion on this subject in this question: Why are Python's 'private' methods not actually private?
I'm not sure if this is what you're looking for, but you could make it a private method, something like this:
def _dont_access_me(self):
return 'Dont Access Me'
technically, it would still be accessible, but it at least lets users know it's intended as a private method
I have the next situation. The goal of the following method is to return the object created from the incoming string. So I have:
class Situation(Generator):
pass
And the method inside parent class:
class Generator(object):
def createsituation(self, stringsituation="situation"):
return "Instance of Situation"
The incoming string always equals to string "situation". Is it possible in python?
You can easily map strings to classes, yes. Classes are just more objects, you can store them in other Python objects.
You can manually build a dictionary mapping strings to classes:
classes = {'situation': Situation}
You can automate this a little by creating a class decorator, perhaps:
classes = {}
def register(cls):
classes[cls.__name__.lower()] = cls
return cls
#register
class Situation(Generator):
# ...
Each class you prefix with #register will be added to the dictionary, with the class name lowercased as the key.
or you can use the globals() function to get a dictionary of all globals in your module. The latter is a little... overkill and also a security hazard, you could end up giving end-users way more access than you bargained for, as that also gives them other classes and functions you didn't mean to expose.
Once you have a dictionary, just access the right class and call it:
class Generator(object):
def createsituation(self, stringsituation="situation"):
return classes[stringsituation]()
If I understood you correctly, you want to create the Situation object from Generator's createsituation method. So you need the appropriate constructor in Situation class with passed string as an argument. Little changes in your code will achieve this:
class Situation(object):
def __init__(self, string):
print string
class Generator(object):
def createsituation(self, stringsituation="situation"):
return Situation(stringsituation)
g = Generator()
sitObj = g.createsituation("new_situation") # prints "new_situation" from Situation constructor
I am trying to create a set of classes as containers of modular blocks of logic. The idea is to be able to mix and match the classes through inheritance (possibly multiple inheritance) to execute any combination of those pieces of modular logic. Here is the structure I currently have:
class Base:
methods = {}
def __init__(self):
"""
This will create an instance attribute copy of the combined dict
of all the methods in every parent class.
"""
self.methods = {}
for cls in self.__class__.__mro__:
# object is the only class that won't have a methods attribute
if not cls == object:
self.methods.update(cls.methods)
def call(self):
"""
This will execute all the methods in every parent
"""
for k,v in self.methods.items():
v(self)
class ParentA(Base):
def method1(self):
print("Parent A called")
methods = {"method":method1}
class ParentB(Base):
def method2(self):
print("Parent B called")
methods = {"method2" : method2}
class Child(ParentA, ParentB):
def method3(self):
print("Child called")
methods = {"method3" : method3}
This seems to work as expected but I was wondering if there is anything I might be missing design wise or if there is something I am trying to do that I should not be doing. Any considerations or feedback on the structure is very welcome. As well as tips on how I could make this more pythonic. Thank you all in advance.
In Python, how do I get a reference to the current class object within a class statement? Example:
def setup_class_members(cls, prefix):
setattr(cls, prefix+"_var1", "hello")
setattr(cls, prefix+"_var2", "goodbye")
class myclass(object):
setup_class_members(cls, "coffee") # How to get "cls"?
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
x = myclass()
x.mytest()
>>> hello
>>> goodbye
Alternatives that I've written off are:
Use locals(): This gives a dict in a class statement that can be written to. This seems to work for classes, however the documentation tells you not to do this. (I might be tempted to go with this alternative if someone can assure me that this will continue to work for some time.)
Add members to the class object after the class statement: My actual application is to derive a PyQt4 QWidget class with dynamically created pyqtProperty class attributes. QWidget is unusual in that it has a custom metaclass. Very roughly, the metaclass compiles a list of pyqtProperties and stores it as additional member. For this reason, properties that are added to the class after creation have no effect. An example to clear this up:
from PyQt4 import QtCore, QtGui
# works
class MyWidget1(QtGui.QWidget):
myproperty = QtCore.pyqtProperty(int)
# doesn't work because QWidget's metaclass doesn't get to "compile" myproperty
class MyWidget2(QtGui.QWidget):
pass
MyWidget2.myproperty = QtCore.pyqtProperty(int)
Please note that the above will work for most programming cases; my case just happens to be one of those unusual corner cases.
For Python 3, the class must be declared as
class myclass(object, metaclass = Meta):
prefix = "coffee"
...
A few other points:
The metaclass may be a callable, not just a class (Python 2&3)
If the base class of your class already has a non-standard metaclass, you have to make sure you call it's __init__() and __new__() methods instead of type's.
The class statement accepts keyword parameters that are passed on to the metaclass (Python 3 only)
A rewrite of mouad's solution in Python 3 using all of the above is...
def MetaFun(name, bases, attr, prefix=None):
if prefix:
attr[prefix+"_var1"] = "hello"
attr[prefix+"_var2"] = "goodbye"
return object.__class__(name, bases, attr)
class myclass(object, metaclass = MetaFun, prefix="coffee"):
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
AFAIK there is two way to do what you want:
Using metaclass, this will create your two variables in class creation time (which i think is what you want):
class Meta(type):
def __new__(mcs, name, bases, attr):
prefix = attr.get("prefix")
if prefix:
attr[prefix+"_var1"] = "hello"
attr[prefix+"_var2"] = "goodbye"
return type.__new__(mcs, name, bases, attr)
class myclass(object):
__metaclass__ = Meta
prefix = "coffee"
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
Create your two class variable in instantiation time:
class myclass(object):
prefix = "coffee"
def __init__(self):
setattr(self.__class__, self.prefix+"_var1", "hello")
setattr(self.__class__, self.prefix+"_var2", "goodbye")
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
N.B: I'm not sure what you want to achieve because if you want to create dynamic variables depending on the prefix variable why are you accessing like you do in your mytest method ?! i hope it was just an example.
Two more approaches you might use:
A class decorator.
def setup_class_members(prefix):
def decorator(cls):
setattr(cls, prefix+"_var1", "hello")
setattr(cls, prefix+"_var2", "goodbye")
return cls
return decorator
#setup_class_members("coffee")
class myclass(object):
# ... etc
Especially if you need to add attributes in various combinations, the decorator approach is nice because it does not have any effect on inheritance.
If you are dealing with a small set of of attributes that you wish to combine in various ways, you can use mixin classes. A mixin class is a regular class, it's just intended to "mix in" various attributes to some other class.
class coffee_mixin(object):
coffee_var1 = "hello"
coffee_var2 = "goodbye"
class tea_mixin(object):
tea_var1 = "good morning old bean"
tea_var2 = "pip pip cheerio"
class myclass(coffee_mixin, tea_mixin):
# ... etc
See zope.interface.declarations._implements for an example of doing this kind of magic. Just be warned that it's a serious maintainability and portability risk.
Obj-C (which I have not used for a long time) has something called categories to extend classes. Declaring a category with new methods and compiling it into your program, all instances of the class suddenly have the new methods.
Python has mixin possibilities, which I use, but mixins must be used from the bottom of the program: the class has to declare it itself.
Foreseen category use-case: Say you have a big class hierarchy that describe different ways of interacting with data, declaring polymorphic ways to get at different attributes. Now a category can help the consumer of these describing classes by implementing a convenient interface to access these methods in one place. (A category method could for example, try two different methods and return the first defined (non-None) return value.)
Any way to do this in Python?
Illustrative code
I hope this clarifies what I mean. The point is that the Category is like an aggregate interface, that the consumer of AppObj can change in its code.
class AppObj (object):
"""This is the top of a big hierarchy of subclasses that describe different data"""
def get_resource_name(self):
pass
def get_resource_location(self):
pass
# dreaming up class decorator syntax
#category(AppObj)
class AppObjCategory (object):
"""this is a category on AppObj, not a subclass"""
def get_resource(self):
name = self.get_resource_name()
if name:
return library.load_resource_name(name)
else:
return library.load_resource(self.get_resource_location())
Why not just add methods dynamically ?
>>> class Foo(object):
>>> pass
>>> def newmethod(instance):
>>> print 'Called:', instance
...
>>> Foo.newmethod = newmethod
>>> f = Foo()
>>> f.newmethod()
Called: <__main__.Foo object at 0xb7c54e0c>
I know Objective-C and this looks just like categories. The only drawback is that you can't do that to built-in or extension types.
I came up with this implementation of a class decorator. I'm using python2.5 so I haven't actually tested it with decorator syntax (which would be nice), and I'm not sure what it does is really correct. But it looks like this:
pycategories.py
"""
This module implements Obj-C-style categories for classes for Python
Copyright 2009 Ulrik Sverdrup <ulrik.sverdrup#gmail.com>
License: Public domain
"""
def Category(toclass, clobber=False):
"""Return a class decorator that implements the decorated class'
methods as a Category on the class #toclass
if #clobber is not allowed, AttributeError will be raised when
the decorated class already contains the same attribute.
"""
def decorator(cls):
skip = set(("__dict__", "__module__", "__weakref__", "__doc__"))
for attr in cls.__dict__:
if attr in toclass.__dict__:
if attr in skip:
continue
if not clobber:
raise AttributeError("Category cannot override %s" % attr)
setattr(toclass, attr, cls.__dict__[attr])
return cls
return decorator
Python's setattr function makes this easy.
# categories.py
class category(object):
def __init__(self, mainModule, override = True):
self.mainModule = mainModule
self.override = override
def __call__(self, function):
if self.override or function.__name__ not in dir(self.mainModule):
setattr(self.mainModule, function.__name__, function)
# categories_test.py
import this
from categories import category
#category(this)
def all():
print "all things are this"
this.all()
>>> all things are this