I am trying to improve my python code and have started using classes to group related methods and variables.
What is the best practice when using a function that is able to access the variables that are initialized in the class? Should I just access the variable in the function? Or explicitly pass the variable to make it clear that I am relying on it?
I've created two examples to show what I mean by this question. Which method is preferred?
# method 1
class UploadForm(object):
def __init__(self, form_data):
self.file_name = form_data.get('file_name')
def validate(self):
agency_name = self.extract_agency_name(self.file_name)
#staticmethod
def extract_agency_name(file_name):
pattern = re.search('^[CFS]Y\d{4} (.+?)[.](?:xls|csv)$', file_name, re.I)
if pattern:
agency_name = pattern.group(1)
return agency_name
# method 2
class UploadForm(object):
def __init__(self, form_data):
self.file_name = form_data.get('file_name')
def validate(self):
agency_name = self.extract_agency_name()
def extract_agency_name(self):
pattern = re.search('^[CFS]Y\d{4} (.+?)[.](?:xls|csv)$', self.file_name, re.I)
if pattern:
agency_name = pattern.group(1)
return agency_name
For reasons below method 2 is preferred.
A member variable should be accessed via self.
By using self, you are making clear that you are referencing file_name variable of the same object.
Decorators can become overheads.
Decorators are wrappers around a method or a variable.
Passing more argument is more memory consuming.
Each argument takes up memory.
Related
I don't think it is because of the scope of the function, but I get a
Unresolved reference at get_all_predicates(examples).count(predicate_list[0])
inside get_entropy_of_attributes(examples, predicate_list) function in my class Tree:
class Tree:
def get_examples(examples, attributes):
for value in examples:
yield dict(zip(attributes, value.strip().replace(" ", "").split(',')))
def get_all_predicates(examples):
return [d['Predicate'] for d in examples]
def get_entropy_of_attributes(examples, predicate_list):
get_all_predicates(examples).count(predicate_list[0])
return 0
examples = list(get_examples(all_examples, name_of_attributes))
predicate_list = list(set(get_all_predicates(examples)))
get_entropy_of_attributes(examples, predicate_list)
all_examples is a list of dictionary and name_of_attributes is a list, that holds values imported from a text file.
all_examples = [{'P_Length': '1.4', 'P_Width': '0.2', 'Predicate': 'I-setosa', 'Sepal_Width': '3.5', 'S_Length': '5.1'}, ...]
name_of_attributes = ["Check","P-Width"]
Any help?
Classes do not have scopes, only namespaces. This means that functions defined within them cannot see other class variables automatically.
class Foo(object):
var = 1 # lets create a class variable
def foo():
print(var) # this doesn't work!
To access a class variable, you need use attribute syntax: either Foo.var (to access via the class) or, if you're writing an instance method, with self.var (to access via the current instance, which will be passed in as the first argument).
class Bar(object):
var = 1
def bar1():
print(Bar.var) # works
def bar2(self):
print(self.var) # also works, if called on an instance, e.g. `Bar().bar2()`
With this kind of setup you can almost fix your current code (but not quite).
def get_entropy_of_attributes(examples, predicate_list):
Tree.get_all_predicates(examples).count(predicate_list[0]) # name the class
return 0
If you call this after the class is fully initialized, it will work without any exceptions (though it's implementation seems a bit nonsensical). However, it doesn't work when you call it to define a class variable, as your current code does. That's because the class object is only created and bound to the class name after all of the class body has been run.
I think the fix for that is probably to redesign your class in a more conventional way. Rather than having class variables set up based on various globals (like all_examples), you should probably create instances of your class by passing in arguments to the constructor and making the other variables you calculate from them instance attributes. I'd try to write it out, but frankly I don't understand what you're doing well enough.
If you want to call class methods, you have to call them with self, e.g.
class myClass:
def __init__(self):
pass
def get_all_predicates(self):
print('asd')
def do_something(self):
self.get_all_predicates() # working
get_all_predicates() # → Unresolved reference
test = myClass()
test.do_something()
See this link for examples for Python classes.
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
I am trying to implement multiple constructors in python and one of the suggestions (through online searching) was to use the classmethod. However, using this, I am having issues with code reuse and modularity. Here is an example where I can create an object based on a supplied file or through some other means:
class Image:
def __init__(self, filename):
self.image = lib.load(filename)
self.init_others()
#classmethod
def from_data(cls, data, header):
cls.image = lib.from_data(data, header)
cls.init_others()
return cos
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4,4)
Now it seems that I cannot do that. The cls.init_others() call fails by saying that I have not provided the object to call it on. I guess I can initialise things in the from_data function itself but then I repeat the code in the init method and the other "constructors". Does anyone know how I can call these other initialiser methods from these #classmethod marked functions? Or perhaps someone knows a better way to initialise these variables.
I come from a C++ background. So still trying to find my way around the python constructs.
Your class method should create and return a new instance of the class, not assign class attributes and return the class itself. As an alternative to the keyword arguments, you could do something like:
class Image:
def __init__(self, image):
self.image = image
self.init_others()
#classmethod
def from_data(cls, data, header):
return cls(lib.from_data(data, header))
#classmethod
def from_filename(cls, filename):
return cls(lib.load(filename))
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4, 4)
This adds the ability to create an instance if you already have the image, too.
I would recommend not trying to create multiple constructors, and use keyword arguments instead:
class Image(object):
def __init__(self, filename=None, data=None, header=None):
if filename is not None:
self.image = lib.load(filename)
elif data is not None and header is not None:
self.image = lib.from_data(data, header)
else:
raise ValueError("You must provide filename or both data and header")
self.init_others()
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4,4)
This is a more Pythonic way to handle this scenario.
You should always pass in self as the first argument to any method that will act on a class instance. Python will not automatically determine the instance you're trying to call the method for unless you do that. So if you want to use a class function like
the_image = Image("file.txt")
the_image.interpolate(foo,bar)
You need to define the method within Image as
def interpolate(self,foo,bar):
# Your code
I have a class that represents a pretty complex object. The objects can be created by many ways: incremental building, by parsing text strings in different formats and by analyzing binary files. So far my strategy was as follows:
Have the constructor (__init__, in my case) initialize all the internal variables to None
Supply different member functions to populate the object
Have those functions return the new, modified object to the caller so we can do sd = SuperDuper().fromString(s)
For example:
class SuperDuper:
def __init__(self):
self.var1 = None
self.var2 = None
self.varN = None
## Generators
def fromStringFormat1(self, s):
#parse the string
return self
def fromStringFormat2(self, s):
#parse the string
return self
def fromAnotherLogic(self, *params):
#parse params
return self
## Modifiers (for incremental work)
def addThis(self, p):
pass
def addThat(self, p):
pass
def removeTheOtherOne(self, p):
pass
The problem is that the class becomes very huge. Unfotunately I am not familiar with OOP pattern designs, but I assume that there is a more ellegant solution for this problem. Is taking the generator functions out of the class (so that fromString(self, s) becomes superDuperFromString(s) a good idea?
What might be a better idea in your case is dependency injection and inversion of control. The idea is to create another class that has all of the settings that you are parsing out of all of these different sources. Then subclasses can define the method to actually parse it. Then when you instantiate the class, pass an instance of the settings class to it:
class Settings(object):
var1 = None
var2 = None
var3 = None
def configure_superduper(self, superduper):
superduper.var1 = self.var1
# etc
class FromString(Settings):
def __init__(self, string):
#parse strings and set var1, etc.
class SuperDuper(object):
def __init__(self, settings): # dependency injection
settings.configure_superduper(self) # inversion of control
# other initialization stuff
sup = SuperDuper(object, FromString(some_string))
Doing it this way has the advantage of adhering more closely to the single responsibility principle which says that a class should only have one (likely to occur) reason to change. If you change the way you're storing any of these strings, then the class has to change. Here, we're isolating that into one simple, separate class for each source of data.
If on the other hand, you think that the data that's being stored is more likely to change than the way it's stored, you might want to go with class methods as Ignacio is suggesting because this is (slightly) more complicated and doesn't really buy you much in that case because when that happens you have to change two classes in this scheme. Of course it doesn't really hurt much either because you'll only have to change one more assignment.
I don't believe it would be, since those all relate directly to the class regardless.
What I would do is make the constructor take arguments to initialize the fields (defaulting to None of course), then turn all the from*() methods into classmethods that construct new objects and return them.
I don't think it is a bad design to have conversion/creation methods inside the class. You could always move it to a separate class and then you would have a Simple Factory which is a very light-weight design pattern.
I'd keep them in the class though :)
Have those functions return the new, modified object to the caller so we can do sd = SuperDuper().fromString(s)
Rarely is this a good idea. While some Python library classes do this, it's not the best approach.
Generally, you want to do this.
class SuperDuper( object ):
def __init__(self, var1=None, var2=None, var3=None):
self.var1 = var1
self.var2 = var2
self.varN = var3
def addThis(self, p):
pass
def addThat(self, p):
pass
def removeTheOtherOne(self, p):
pass
class ParseString( object ):
def __init__( self, someString ):
pass
def superDuper( self ):
pass
class ParseString_Format1( ParseString ):
pass
class ParseString_Format2( ParseString ):
pass
def parse_format1( string ):
parser= ParseString_Format1( string )
return parser.superDuper()
def parse_format2( string ):
parser= ParseString_Format2( string )
return parser.superDuper()
def fromAnotherLogic( **kw ):
return SuperDuper( **kw )
There are two unrelated responsibilities: the object and the string representations of the object.
Do Not Conflate Objects and String Representations.
Objects and Parsing must be kept separate. After all, the compiler is not part of the code that's produced. An XML parser and the Document Object Model are generally separate objects.
Goal: Make it possible to decorate class methods. When a class method gets decorated, it gets stored in a dictionary so that other class methods can reference it by a string name.
Motivation: I want to implement the equivalent of ASP.Net's WebMethods. I am building this on top of google app engine, but that does not affect the point of difficulty that I am having.
How it Would look if it worked:
class UsefulClass(WebmethodBaseClass):
def someMethod(self, blah):
print(blah)
#webmethod
def webby(self, blah):
print(blah)
# the implementation of this class could be completely different, it does not matter
# the only important thing is having access to the web methods defined in sub classes
class WebmethodBaseClass():
def post(self, methodName):
webmethods[methodName]("kapow")
...
a = UsefulClass()
a.post("someMethod") # should error
a.post("webby") # prints "kapow"
There could be other ways to go about this. I am very open to suggestions
This is unnecessary. Just use getattr:
class WebmethodBaseClass():
def post(self, methodName):
getattr(self, methodName)("kapow")
The only caveat is that you have to make sure that only methods intended for use as webmethods can be used thus. The simplest solution, IMO, is to adopt the convention that non-webmethods start with an underscore and have the post method refuse to service such names.
If you really want to use decorators, try this:
def webmethod(f):
f.is_webmethod = True
return f
and get post to check for the existence of the is_webmethod attribute before calling the method.
This would seem to be the simplest approach to meet your specs as stated:
webmethods = {}
def webmethod(f):
webmethods[f.__name__] = f
return f
and, in WebmethodBaseClass,
def post(self, methodName):
webmethods[methodName](self, "kapow")
I suspect you want something different (e.g., separate namespaces for different subclasses vs a single global webmethods dictionary...?), but it's hard to guess without more info exactly how your desires differ from your specs -- so maybe you can tell us how this simplistic approach fails to achieve some of your desiderata, so it can be enriched according to what you actually want.
class UsefulClass(WebmethodBaseClass):
def someMethod(self, blah):
print(blah)
#webmethod
def webby(self, blah):
print(blah)
class WebmethodBaseClass():
def post(self, methodName):
method = getattr(self, methodName)
if method.webmethod:
method("kapow")
...
def webmethod(f):
f.webmethod = True
return f
a = UsefulClass()
a.post("someMethod") # should error
a.post("webby") # prints "kapow"