Right way to set variables at python class - python

Which is the right way to work with variables inside a class?
1- setting them as class attributes where we get them and access them from class itself:
class NeuralNetwork(object):
def __init__(self, topology):
self.topology = topology
self.buildLayers()
def buildLayers(self):
for layer in self.topology:
#do thing
2- passing them through methods that we need them without assign at class if they are not really useful variables:
class NeuralNetwork(object):
def __init__(self, topology):
self.buildLayers(topology)
def buildLayers(self, topology):
for layer in topology:
#do thing
3- a mix of the above two:
class NeuralNetwork(object):
def __init__(self, topology):
self.topology = topology
self.buildLayers(self.topology) # or self.buildLayers(topology) ?
def buildLayers(self, topology):
for layer in topology:
#do thing
I think that the first one is the correct, but it don't let you to reuse the function for different purposes without assigning a new value to the variable, what would look like these:
self.topology = x
self.buildLayers()
What looks weird and you don't really understand that changing self.topology is affecting the call of self.buildLayers()

In general the first way is the "really object oriented" way, and much preferred over the second and the third.
If you want your buildLayers function to be able to change the topology occasionally, give it a param. topology with default value = None.
As long as you don't pass that param. at calling buildLayers, it will use this.topology. If you pass it, it will use the one you passed, and (if you wish) change this.topology to it.
By the way, while it's wise to stick to rules like this in the beginning, there are no real dogmas in programming. As experience grows, you'll find that to each rule there are many perfectly sane exceptions.
That's the fun of programming, you never stop learning from experience.

1st one is correct and recommended. As that will be object dependent.

Related

Is it possible to instantiate multiple instances of a class through a single classmethod call?

So I've used python as a functional language for a while but I'm trying to do thing "right" and use classes now... and falling down. I'm trying to write a classmethod that can instantiate multiple members of the class (use case is load rows from SQLAlchemy.) I'd like to just be able to call the classmethod and have it return a status code (success/failure) rather than returning a list of objects. Then to access the objects I'll iterate through the class. Here's my code so far (which fails to iterate when I use the classmethod, works fine when I use the normal constructor.) Am I way off-base/crazy here? What's the "pythonic" way to do this? Any help is appreciated and thank you.
class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))
#classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst
class Credentials(KeepRefs):
def __init__(self,name, username, password):
super(Credentials, self).__init__()
self.name=name
self.username=username
self.password=password
#classmethod
def loadcreds(cls):
Credentials('customer1','bob','password')
return True
success = Credentials.loadcreds()
for i in Credentials.get_instances():
print (i.name)
In your own words - yes, you are off-base and crazy :)
Status-Codes are a thing of C, not languages with proper exception semantics as Python. Modifying global state is a sure recipe for disaster. So - don't do it. Return a list of objects. Throw an exception if something disastrous happens, and just return an empty list if there happen to be no objects. This allows the client code to just do
for item in Thingies.load_thingies():
... # this won't do anything if load_thingies gave us an empty list
without having to painstakingly check something before using it.
Functional languages have certain advantages, and you are going too far the other way in your exploration of the procedural style. Global variables and class variable have their place, but what will happen if you need to fire off two SQAlchemy queries and consume the results in parallels? The second query will stomp over the class attributes that the first one still needs, is what. Using an object attribute (instance attribute) solves the problem, since each result contains its own handle.
If your concern is to avoid pre-fetching the array of results, you are in luck because Python offers the perfect solution: Generators, which are basically lazy functions. They are so nicely integrated in Python, I bet you didn't know you've been using them with every for-loop you write.

How to Link Multiple Classes Together Efficiently

Background:
I have been working on a game in Python, and in order to keep everything clean, organized and in a pythonic way, I have a folder containing multiple python files, each containing one big class, for example "MapEngine" or "NPCEngine".
From main.py, I am loading each class from each file and "glueing everything together with a "Game" class, such as:
from folder import *
class Game:
def __init__(self):
self.MapEngine = MapEngine.MapEngine()
...
def loop(self):
...
Since classes such as "CollisionEngine" requires data from other classes such as, "MapEngine", I usually assign some variables in the former (i.e. CollisionEngine) to the latter (i.e MapEngine), in order to use MapEngine's loaded map data or functions:
class CollisionEngine:
def __init__(self, MapClass, ...):
self.MapEngine = MapClass
Problem:
Well, since many classes have to be linked to others, it became hard after a while to figure out which class to load first in order to assign variables. Furthermore, classes like "EventEngine" need to have access to every other class. My code became hard to read, and I have trouble when 2 classes are equally important to each other.
Question:
I have heard of class inheritance, but I do not think it can be applied here because each class is very different as in its function. Therefore, is there a way to beautifully link every class together, as if it was all part of one big class? In other words, is there a way to refer to variables from other classes, from within a class?
(My thoughts: Perhaps, I can write a class called "Request", and it will act as a top level class manager. Although, I think I will have to use functions such as exec() or eval(), which are not efficient and are somewhat dangerous.)
This is my first post, I've tried to be as explicit as possible, please ask me for clarification, & thank you for your reply!
Consider separating your project into layers - that should help you keep things more organised and make the imports more natural.
The principle is that lower layers of your code "cake" shouldn't depend on (read: import) upper layers of your code.
For example you might have a foundation layer which contains common data structures, util classes and algorithms that are used in lots of your code at various layers.
Then you might have a model layer which depends on the foundation layer (i.e. data structures/utils/algorithms) but nothing else. The model layer provides models of objects within the domain.
You might then have a game layer which depends on the model layer (so it would be quite reasonable for modules in your game layer to import things from the model layer, but not vice versa).
Well, after many tries, I have figured out a (sketchy) way of solving my problem. Of course, as eddiewould suggested, I will have a better organization and multiple layers for my code, but if one would like to have multiple classes all linked together, simply include a variable to the main class (that called every class) to every class. I believe that a code snippet will explain it better:
main.py
engine_folder
----> engine_1.py
----> engine_2.py
in main.py, engine_1 and engine_2 are loaded:
from engine_folder import engine_1, engine_2
class game:
def __init__(self):
self.engine_1 = engine_1.engine(self, ...)
self.engine_2 = engine_2.engine(self, ...)
#where engine_1.engine and engine_2.engine are
#two classes that need to transfer data between
#each other
def run(self):
self.engine_1.run()
self.engine_2.run()
Notice how engine_1.engine's first argument is self, which refers to the top level class which called this class. Now, in engine_1, if we would want to print a variable from engine_2, the class would look similar to this:
class engine:
def __init__(self, top_level_class, ...):
self.top_level_class = top_level_class
def run(self):
print self.top_level_class.engine_2.random_var
This is very beautiful (besides the fact that print self.top_level_class.engine_2.random_var is very long), but compared to something like:
class EventEngine:
def __init__(self, Camera_Class, Map_Class, Character_Class, Skill_Class,
Interface_Class, Sprite_Class, Dialog_Class, Game_Class,
Item_Class):
self.ItemEngine = Item_Class
self.GameEngine = Game_Class
self.DialogEngine = Dialog_Class
self.SpriteEngine = Sprite_Class
self.SkillEngine = Skill_Class
self.CameraEngine = Camera_Class
self.MapEngine = Map_Class
self.CharacterEngine = Character_Class
self.IEngine = Interface_Class
The new version:
class EventEngine:
def __init__(self, top_level_class):
self.top = top_level_class
#a var from Map_Class can be called as such:
#self.top.MapEngine.map[0][1]
#and I can call variables from every class, not only those I
#have loaded like before
is much better and much cleaner.

Redefine a python function based on another class function based on type

I'm more of an engineer and less of a coder, but I know enough python and C++ to be dangerous.
I'm creating a python vector/matrix class as a helper class based upon numpy as well as cvxopt. The overall goal (which I've already obtained... the answer to this question will just make the class better) is to make dot products and other processes more unified and easier for numerical methods.
However, I'd like to make my helper class even more transparent. What I'd like to do is to redefine the cvxopt.matrix() init function based upon the current variable which was used. This is to say, if I have a custom matrix: "cstmat", I'd like the function "cvxopt.matrix(cstmat)" to be defined by my own methods instead of what is written in the cvxopt class.
In short, I'd like to "intercept" the other function call and use my own function.
The kicker, though, is that I don't want to take over cvxopt.matrix(any_other_type). I just want to redefine the function when it's called upon my own custom class. Is this possible?
Thanks,
Jon
You can do this, but it's not pretty.
You can do probably something along these lines:
cvxopt._orig_matrix = cvxopt.matrix
def my_matrix(*args, **kwargs):
if isinstance(arg[0], cstmat):
# do your stuff here
else:
cvxopt._orig_matrix(*args, **kwargs)
cvxopt.matrix = my_matrix
But you're probably better off finding a less weird way. And no guarantees that won't forget who "self" is.
Better would be to use inheritance! Kinda like this:
class Cstmat(cvsopt.matrix):
def __init__(self, ...):
pass
def matrix(self, arg):
if isinstance(arg, cstmat):
# do your stuff here
else:
cvsopt.matrix(arg)

Class design: methods that share a lot of the same code

I want to create a class with two methods at this point (I also want to be able to
alter the class obviously).
class ogrGeo(object):
def __init__(self):
pass
def CreateLine(self, o_file, xy):
#lots of code
def CreatePoint(self, o_file, xy):
# lot's of the same code as CreateLine(),
# only minor differences
To keep things as clean and to to repeat as
less code as possible I'm asking for some advise. The two methods CreateLine()
and CreatePoint() share a lot of code. To reduce redundance:
Should a define third method that both methods can call?
In this case you could still call
o = ogrGeo()
o.CreateLine(...)
o.CreatePoint(...)seperatly.
Or should I merge them into one method? Is there another solution I haven't thought about or know nothing about?
Thanks already for any suggestions.
Whether you should merge the methods into one is a matter of API design. If the functions have a different purpose, then you keep them seperate. I would merge them if client code is likely to follow the pattern
if some_condition:
o.CreateLine(f, xy)
else:
o.CreatePoint(f, xy)
But otherwise, don't merge. Instead, refactor the common code into a private method, or even a freestanding function if the common code does not touch self. Python has no notion of "private method" built into the language, but names with a leading _ will be recognized as such.
It's perfectly normal to factor out common code into a (private) helper method:
class ogrGeo(object)
def __init__(self):
pass
def CreateLine(self, o_file, xy):
#lots of code
value = self._utility_method(xy)
def CreatePoint(self, o_file, xy):
# lot's of the same code as CreateLine(),
# only minor differences
value = self._utility_method(xy)
def _utility_method(self, xy):
# Common code here
return value
The method could return a value, or it could directly manipulate the attributes on self.
A word of advice: read the Python style guide and stick to it's conventions. Most other python projects do, and it'll make your code easier to comprehend for other Python developers if you do.
For the pieces of code that will overlap, consider whether those can be their own separate functions as well. Then CreateLine would be comprised of several calls to certain functions, with parameter choices that make sense for CreateLine, meanwhile CreatePoint would be several function calls with appropriate parameters for creating a point.
Even if those new auxiliary functions aren't going to be used elsewhere, it's better to modularize them as separate functions than to copy/paste code. But, if it is the case that the auxialiary functions needed to create these structures are pretty specific, then why not break them out into their own classes?
You could make an "Object" class that involves all of the basics for creating objects, and then have "Line" and "Point" classes which derive from "Object". Within those classes, override the necessary functions so that the construction is specific, relying on auxiliary functions in the base "Object" class for the portions of code that overlap.
Then the ogrGeo class will construct instances of these other classes. Even if the ultimate consumer of "Line" or "Shape" doesn't need a full blown class object, you can still use this design, and give ogrGeo the ability to return the sub-pieces of a Line instance or a Point instance that the consumer does wish to use.
It hardly matters. You want the class methods to be as usable as possible for the calling programs, and it's slightly easier and more efficient to have two methods than to have a single method with an additional parameter for the type of object to be created:
def CreateObj(self, obj, o_file, xy) # obj = 0 for Point, 1 for Line, ...
Recommendation: use separate API calls and factor the common code into method(s) that can be called within your class.
You as well could go the other direction. Especially if the following is the case:
def methA/B(...):
lots of common code
small difference
lots of common code
then you could do
def _common(..., callback):
lots of common code
callback()
lots of common code
def methA(...):
def _mypart(): do what A does
_common(..., _mypart)
def methB(...):
def _mypart(): do what B does
_common(..., _mypart)

Why do new instances of a class share members with other instances?

class Ball:
a = []
def __init__(self):
pass
def add(self,thing):
self.a.append(thing)
def size(self):
print len(self.a)
for i in range(3):
foo = Ball()
foo.add(1)
foo.add(2)
foo.size()
I would expect a return of :
2
2
2
But I get :
2
4
6
Why is this? I've found that by doing a=[] in the init, I can route around this behavior, but I'm less than clear why.
doh
I just figured out why.
In the above case, the a is a class attribute, not a data attribute - those are shared by all Balls(). Commenting out the a=[] and placing it into the init block means that it's a data attribute instead. (And, I couldn't access it then with foo.a, which I shouldn't do anyhow.) It seems like the class attributes act like static attributes of the class, they're shared by all instances.
Whoa.
One question though : CodeCompletion sucks like this. In the foo class, I can't do self.(variable), because it's not being defined automatically - it's being defined by a function. Can I define a class variable and replace it with a data variable?
What you probably want to do is:
class Ball:
def __init__(self):
self.a = []
If you use just a = [], it creates a local variable in the __init__ function, which disappears when the function returns. Assigning to self.a makes it an instance variable which is what you're after.
For a semi-related gotcha, see how you can change the value of default parameters for future callers.
"Can I define a class variable and replace it with a data variable?"
No. They're separate things. A class variable exists precisely once -- in the class.
You could -- to finesse code completion -- start with some class variables and then delete those lines of code after you've written your class. But every time you forget to do that nothing good will happen.
Better is to try a different IDE. Komodo Edit's code completions seem to be sensible.
If you have so many variables with such long names that code completion is actually helpful, perhaps you should make your classes smaller or use shorter names. Seriously.
I find that when you get to a place where code completion is more helpful than annoying, you've exceeded the "keep it all in my brain" complexity threshold. If the class won't fit in my brain, it's too complex.

Categories

Resources