Is it OK if objects from different classes interact with each other? - python

I just started to use the object oriented programming in Python. I wander if it is OK if I create a method of a class which use objects from another class. In other words, when I call a method of the first class I give an object from the second class as one of the arguments. And then, the considered methods (of the first class) can manipulate by the object from the second class (to get its attributes or use its methods). Is it allowed in Python? Is it not considered as a bad programming style?
Is it OK if I instantiate objects from the second class withing a method of the first class. In other words, if I call a method from the first class it instantiate objects fro the second class.
Thank you in advance for any help.

If you're talking about passing an instance of one object to the method of a another one, then yes of course it's allowed! And it's considered fine practice.
If you want to know more about good object oriented coding, may I offer some suggested readings:
Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides
Known as the Gang Of Four book, this lays out a number of design patterns that seem to show up in object oriented code time and time again. This is a good place to go for ideas on how to handle certain problems in a good object oriented way.
Another good one:
Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant , William Opdyke, Don Roberts
This is a great book for learning what NOT to do when writing object oriented code, and how to fix it to make it better when you do encounter it. It offers a list of code smells that suggest bad object oriented code and a reference section of refactorings that provide instructions on how to fix those smells and make them more object oriented.

What you're talking about is fine. In fact most data types (string, int, boolean, etc.) in Python are objects, so pretty much every method works in the way you described.

The answer is that it os MORE than OK, it's in fact the whole point.
What is not "OK" is when objects start fiddling with the internals of each other. You can prevent this from happening accidentally, by calling things that are meant to be internal with a leading underscore (or two, which makes it internal also for subclasses). This works as a little marker for other programmers that you aren't supposed to use it, and that it's not official API and can change.

I see no problem with that, it happens all the time. Do you have a specific problem you're trying to solve or just asking a general question without a context?

The Law of Demeter is general guidance on which methods and objects you can interact with in good faith.
It is guidance. You can make code that works that doesn't follow the LoD, but it is a good guide and helps you build "structure shy systems" -- something you will appreciate later when you try to make big changes.
http://en.wikipedia.org/wiki/Law_of_Demeter
I recommend reading up on good OO practices and principles when you're not coding. Maybe a few papers or a chapter of a book each evening or every other day. Try the SOLID principles. You can find a quick reference to them here:
http://agileinaflash.blogspot.com/2009/03/solid.html

Related

Why do Python programmers not use properties very often?

I am using both Python and C#.
In C# it is almost required to use properties.
In Python it is possible to use properties, but I do not see them in use very often.
Is there a specific reason why Pythonistas to not use properties as much as programmers of other languages?
Python's philosophy
Python is a language for consenting adults.
— Alan Runyan Cofounder of Plone
In Python the philosophy is that we're all responsible users (maybe an improvement on the term "consenting adults"), so we do not protect data unless there we believe there to be a benefit for the user.
Cultural evidence:
Python read-only property
Tutor mailing list, 2003: What is Pythonic
Reasons we might use properties:
Maybe the attribute is something that can be calculated and is not needed often, thus saving space.
Maybe the attribute is required to be a specific type that could easily be given the wrong type or value by a user, and so you can create value for the user by managing the access to it.
Maybe the attribute would be better as a function, but it started out as a simple dotted lookup but then grew into one of the two above, so we keep the API to avoid breaking users.
Reasons we might not use properties:
Maybe the code is only going to be used by the author, making it less important to protect the users.
Maybe we are trying to coax more performance from the code by precalculating attributes, and don't mind the memory tradeoffs.
Maybe we want our code to be more terse/less verbose.
It's a matter of judgment
Note that the reasons given are matters of the programmer's judgment. Managed properties are not required by the language, but they are a feature. If you think your users don't need them, you can avoid paying the computational costs to do so.
Conclusion
Other languages do not necessarily share this philosophy - instead the culture is that you must write code that you will only use yourself as if you are a community of users. That is why they will have more use of these kinds of data-hiding than you typically see in Python code.

Is it Pythonic to use objects wherever possible?

Newbie Python question here - I am writing a little utility in Python to do disk space calculations when given the attributes of 2 different files.
Should I create a 'file' class with methods appropriate to the conversion and then create each file as an instance of that class? I'm pretty new to Python, but ok with Perl, and I believe that in Perl (I may be wrong, being self-taught), from the examples that I have seen, that most Perl is not OO.
Background info - These are IBM z/OS (mainframe) data sets, and when given the allocation attributes for a file on a specific disk type and file organisation (it's block size) and then given the allocation parameters for a different disk type & organisation, the space requirements can vary enormously.
Definition nitpicking preface: Everything in Python is technically an object, even functions and numbers. I'm going to assume you mean classes vs. functions in your question.
Actually I think one of the great things about Python is that it doesn't embrace classes for absolutely everything as some other languages (e.g., Java and C#).
It's perfectly acceptable in Python (and the built-in modules do this a lot) to define module level functions rather than encapsulating all logic in objects.
That said, classes do have their place, for example when you perform multiple actions on a single piece of data, and especially when these actions change the data and you want to keep its state encapsulated.
For Your Question and you requirements ..a short answer is "No"
The use of objects is not in itself "object oriented". Functional programming uses objects, too, just not in the same way. Python can be used in a very FP way, even though Python uses objects heavily behind the scenes.
Overuse of primitives can be a problem, but it's impossible to say whether that applies to your case without more data.
I think of OO as an interface design approach: If you are creating tools that are straightforward to interact with (and substitutable) as objects with predictable methods, then by all means, create objects. But if the interactions are straightforward to describe with module-level functions, then don't try too hard to engineer your code into classes.
First and foremost - Pythonic is a term that needs to disappear, preferably with everyone who uses it. It doesn't mean anything and it's used by people who can't use reason to justify anything, so they need a mandatory term to justify their nonsense.
But to the point you never HAVE to use object oriented concepts in your software development, as everything OOP can as easily be written with functions and solid spaghetti stringers. But the question is - do use of objects makes sense in my solution?
To understand when and how to use it, you have to ask what exactly is object oriented programming. And this was already very well explained in very old, but also free, book called Thinking in java which I consider to be the 101 bible of thinking on OO terms. I strongly urge you to grab a free copy and read couple of first chapters.
Because if you don't understand the object oriented approach, how can you apply it properly? When you do - then when to use it, or not use it, becomes clear, because you can clearly translate real life items and interactions into abstract objects. And this is the guideline - when the translation of given action, item or data to OOP model is straightforward and logical - then you should do it.

understanding proper python code organization [duplicate]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Much of my programming background is in Java, and I'm still doing most of my programming in Java. However, I'm starting to learn Python for some side projects at work, and I'd like to learn it as independent of my Java background as possible - i.e. I don't want to just program Java in Python. What are some things I should look out for?
A quick example - when looking through the Python tutorial, I came across the fact that defaulted mutable parameters of a function (such as a list) are persisted (remembered from call to call). This was counter-intuitive to me as a Java programmer and hard to get my head around. (See here and here if you don't understand the example.)
Someone also provided me with this list, which I found helpful, but short. Anyone have any other examples of how a Java programmer might tend to misuse Python...? Or things a Java programmer would falsely assume or have trouble understanding?
Edit: Ok, a brief overview of the reasons addressed by the article I linked to to prevent duplicates in the answers (as suggested by Bill the Lizard). (Please let me know if I make a mistake in phrasing, I've only just started with Python so I may not understand all the concepts fully. And a disclaimer - these are going to be very brief, so if you don't understand what it's getting at check out the link.)
A static method in Java does not translate to a Python classmethod
A switch statement in Java translates to a hash table in Python
Don't use XML
Getters and setters are evil (hey, I'm just quoting :) )
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python
(And if you find this question at all interesting, check out the link anyway. :) It's quite good.)
Don't put everything into classes. Python's built-in list and dictionaries will take you far.
Don't worry about keeping one class per module. Divide modules by purpose, not by class.
Use inheritance for behavior, not interfaces. Don't create an "Animal" class for "Dog" and "Cat" to inherit from, just so you can have a generic "make_sound" method.
Just do this:
class Dog(object):
def make_sound(self):
return "woof!"
class Cat(object):
def make_sound(self):
return "meow!"
class LolCat(object):
def make_sound(self):
return "i can has cheezburger?"
The referenced article has some good advice that can easily be misquoted and misunderstood. And some bad advice.
Leave Java behind. Start fresh. "do not trust your [Java-based] instincts". Saying things are "counter-intuitive" is a bad habit in any programming discipline. When learning a new language, start fresh, and drop your habits. Your intuition must be wrong.
Languages are different. Otherwise, they'd be the same language with different syntax, and there'd be simple translators. Because there are not simple translators, there's no simple mapping. That means that intuition is unhelpful and dangerous.
"A static method in Java does not translate to a Python classmethod." This kind of thing is really limited and unhelpful. Python has a staticmethod decorator. It also has a classmethod decorator, for which Java has no equivalent.
This point, BTW, also included the much more helpful advice on not needlessly wrapping everything in a class. "The idiomatic translation of a Java static method is usually a module-level function".
The Java switch statement in Java can be implemented several ways. First, and foremost, it's usually an if elif elif elif construct. The article is unhelpful in this respect. If you're absolutely sure this is too slow (and can prove it) you can use a Python dictionary as a slightly faster mapping from value to block of code. Blindly translating switch to dictionary (without thinking) is really bad advice.
Don't use XML. Doesn't make sense when taken out of context. In context it means don't rely on XML to add flexibility. Java relies on describing stuff in XML; WSDL files, for example, repeat information that's obvious from inspecting the code. Python relies on introspection instead of restating everything in XML.
But Python has excellent XML processing libraries. Several.
Getters and setters are not required in Python they way they're required in Java. First, you have better introspection in Python, so you don't need getters and setters to help make dynamic bean objects. (For that, you use collections.namedtuple).
However, you have the property decorator which will bundle getters (and setters) into an attribute-like construct. The point is that Python prefers naked attributes; when necessary, we can bundle getters and setters to appear as if there's a simple attribute.
Also, Python has descriptor classes if properties aren't sophisticated enough.
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python. Correct. Python uses optional arguments instead of method overloading.
The bullet point went on to talk about closure; that isn't as helpful as the simple advice to use default argument values wisely.
One thing you might be used to in Java that you won't find in Python is strict privacy. This is not so much something to look out for as it is something not to look for (I am embarrassed by how long I searched for a Python equivalent to 'private' when I started out!). Instead, Python has much more transparency and easier introspection than Java. This falls under what is sometimes described as the "we're all consenting adults here" philosophy. There are a few conventions and language mechanisms to help prevent accidental use of "unpublic" methods and so forth, but the whole mindset of information hiding is virtually absent in Python.
The biggest one I can think of is not understanding or not fully utilizing duck typing. In Java you're required to specify very explicit and detailed type information upfront. In Python typing is both dynamic and largely implicit. The philosophy is that you should be thinking about your program at a higher level than nominal types. For example, in Python, you don't use inheritance to model substitutability. Substitutability comes by default as a result of duck typing. Inheritance is only a programmer convenience for reusing implementation.
Similarly, the Pythonic idiom is "beg forgiveness, don't ask permission". Explicit typing is considered evil. Don't check whether a parameter is a certain type upfront. Just try to do whatever you need to do with the parameter. If it doesn't conform to the proper interface, it will throw a very clear exception and you will be able to find the problem very quickly. If someone passes a parameter of a type that was nominally unexpected but has the same interface as what you expected, then you've gained flexibility for free.
The most important thing, from a Java POV, is that it's perfectly ok to not make classes for everything. There are many situations where a procedural approach is simpler and shorter.
The next most important thing is that you will have to get over the notion that the type of an object controls what it may do; rather, the code controls what objects must be able to support at runtime (this is by virtue of duck-typing).
Oh, and use native lists and dicts (not customized descendants) as far as possible.
The way exceptions are treated in Python is different from
how they are treated in Java. While in Java the advice
is to use exceptions only for exceptional conditions this is not
so with Python.
In Python things like Iterator makes use of exception mechanism to signal that there are no more items.But such a design is not considered as good practice in Java.
As Alex Martelli puts in his book Python in a Nutshell
the exception mechanism with other languages (and applicable to Java)
is LBYL (Look Before You Leap) :
is to check in advance, before attempting an operation, for all circumstances that might make the operation invalid.
Where as with Python the approach is EAFP (it's easier to Ask for forgiveness than permission)
A corrollary to "Don't use classes for everything": callbacks.
The Java way for doing callbacks relies on passing objects that implement the callback interface (for example ActionListener with its actionPerformed() method). Nothing of this sort is necessary in Python, you can directly pass methods or even locally defined functions:
def handler():
print("click!")
button.onclick(handler)
Or even lambdas:
button.onclick(lambda: print("click!\n"))

Very basic OO: changing attribute of a method

I'm certain this has been asked a million times, but it's difficult to search for something when you don't know the correct terminology :(
I'm attempting (again... I've never understood OO, since I got taught it very badly 8 years ago, and avoid it as much as possible, to the horror of every other programmer I know - my mind doesn't seem wired to get it, at all) to teach myself OO and PyQt simultaneously.
I don't even know if this is logically possible, but I've got a PyQt action, which is referred to by 2 different things; one of the arguments of the action is an Icon. When the action called by one of those things, I'd like to change the icon; code snippet:
self.menu()
self.toolbar()
self.actions()
def menu(self):
self.fileMenu = QtGui.QMenu("&File", self)
self.fileMenu.addAction(self.exitAct)
def toolbar(self):
self.toolbar = self.addToolBar("Exit")
self.toolbar.addAction(self.exitAct)
def actions(self):
self.exitIcon = QtGui.QIcon('exit.png')
self.exitAct = QtGui.QAction(self.exitIcon, "&Exit", self, triggered=self.close)
In the toolbar, I'd like a different icon (exitdoor.png). The documentation for QtIcon has an addFile method, so I tried:
self.toolbar.addAction(self.exitAct)
self.exitIcon.addFile("exitdoor.png")
but this didn't work, with the error ("'QToolBar' object has no attribute 'addFile'"), and
self.exitAct.addFile("exitdoor.png")
with the error 'QAction' object has no attribute 'addFile' (I do understand why this doesn't work and what the error means).
What's my stupid mistake?! (Apart from the mistake of putting myself through the pain of continuing to try and learn OO...)
'QToolBar' object has no attribute 'addFile'
Hmm, since you called addFile on self.exitIcon, it looks like you have the wrong kind of object in the self.exitIcon variable. It seems you want it to be a QtGui.QIcon type, but instead it's a QToolBar type.
You should look at where you are making assignments to self.exitIcon.
In this case, trying to learn object-oriented programming through Python is not the easiest way. Python is a fine object-oriented language, but it does not catch your errors as immediately as other languages. When you get an error like the above, the mistake was not in that line of code, but rather in a line of code that ran a while ago. Other languages would catch the mistake even before you run your program, and point you directly at the line you need to fix. It might be worthwhile for you to practice a little basic Java to get trained in OOP by a strict teacher before you go off into the wilds of Python.
I'm not familiar with PyQt and only a beginner with Python, but I have quite a bit of experience with other OO languages (primarily C++ and Java). It looks like you need to determine what kind of object is stored in the fields exitIcon and exitAct. From there, you need to find out what attributes these objects have and find the one which you can change to get the behavior you want.
More thoughts:
Somewhere between the execution of self.exitIcon = QtGui.QIcon('exit.png') and self.exitIcon.addFile("exitdoor.png") self.exitIcon is changed to refer to a QToolBar. I suggest that you start sprinkling your code with print statements so you can trace the execution of your code and find out how this variable was changed.
After talking to some much cleverer people than me, the short answer is that what I was trying to do is seemingly impossible. Once an action has been defined, it is not possible to change any attribute of it.
At the moment, my knowledge of python isn't great enough to understand exactly why this is (or how I could have realised this from the docs), but it seems that when an action is defined, it is effectively a blackbox stored in memory, and other objects can only use, and not modify, the blackbox.
Further comments still welcome!

Are accessors in Python ever justified?

I realize that in most cases, it's preferred in Python to just access attributes directly, since there's no real concept of encapsulation like there is in Java and the like. However, I'm wondering if there aren't any exceptions, particularly with abstract classes that have disparate implementations.
Let's say I'm writing a bunch of abstract classes (because I am) and that they represent things having to do with version control systems like repositories and revisions (because they do). Something like an SvnRevision and an HgRevision and a GitRevision are very closely semantically linked, and I want them to be able to do the same things (so that I can have code elsewhere that acts on any kind of Repository object, and is agnostic of the subclass), which is why I want them to inherit from an abstract class. However, their implementations vary considerably.
So far, the subclasses that have been implemented share a lot of attribute names, and in a lot of code outside of the classes themselves, direct attribute access is used. For example, every subclass of Revision has an author attribute, and a date attribute, and so on. However, the attributes aren't described anywhere in the abstract class. This seems to me like a very fragile design.
If someone wants to write another implementation of the Revision class, I feel like they should be able to do so just by looking at the abstract class. However, an implementation of the class that satisfies all of the abstract methods will almost certainly fail, because the author won't know that they need attributes called 'author' and 'date' and so on, so code that tries to access Revision.author will throw an exception. Probably not hard to find the source of the problem, but irritating nonetheless, and it just feels like an inelegant design.
My solution was to write accessor methods for the abstract classes (get_id, get_author, etc.). I thought this was actually a pretty clean solution, since it eliminates arbitrary restrictions on how attributes are named and stored, and just makes clear what data the object needs to be able to access. Any class that implements all of the methods of the abstract class will work... that feels right.
Anyways, the team I'm working with hates this solution (seemingly for the reason that accessors are unpythonic, which I can't really argue with). So... what's the alternative? Documentation? Or is the problem I'm imagining a non-issue?
Note: I've considered properties, but I don't think they're a cleaner solution.
Note: I've considered properties, but I don't think they're a cleaner solution.
But they are. By using properties, you'll have the class signature you want, while being able to use the property as an attribute itself.
def _get_id(self):
return self._id
def _set_id(self, newid):
self._id = newid
Is likely similar to what you have now. To placate your team, you'd just need to add the following:
id = property(_get_id, _set_id)
You could also use property as a decorator:
#property
def id(self):
return self._id
#id.setter
def id(self, newid):
self._id = newid
And to make it readonly, just leave out set_id/the id.setter bit.
You've missed the point. It isn't the lack of encapsulation that removes the need for accessors, it's the fact that, by changing from a direct attribute to a property, you can add an accessor at a later time without changing the published interface in any way.
In many other languages, if you expose an attribute as public and then later want to wrap some code round it on access or mutation then you have to change the interface and anyone using the code has at the very least to recompile and possibly to edit their code also. Python isn't like that: you can flip flop between attribute or property just as much as you want and no code that uses the class will break.
Only behind a property.
"they should be able to do so just by looking at the abstract class"
Don't know what this should be true. A "programmer's guide", a "how to extend" document, plus some training seems appropriate to me.
"the author won't know that they need attributes called 'author' and 'date' and so on".
In that case, the documentation isn't complete. Perhaps the abstract class needs a better docstring. Or a "programmer's guide", or a "how to extend" document.
Also, it doesn't seem very difficult to (1) document these attributes in the docstring and (2) provide default values in the __init__ method.
What's wrong with providing extra support for programmers?
It sounds like you have a social problem, not a technical one. Writing code to solve a social problem seems like a waste of time and money.
The discussion already ended a year ago, but this snippet seemed telltale, it's worth discussing:
However, an implementation of the
class that satisfies all of the
abstract methods will almost certainly
fail, because the author won't know
that they need attributes called
'author' and 'date' and so on, so code
that tries to access Revision.author
will throw an exception.
Uh, something is deeply wrong. (What S. Lott said, minus the personal comments).
If these are required members, aren't they referenced (if not required) in the constructor, and defined by docstring? or at very least, as required args of methods, and again documented?
How could users of the class not know what the required members are?
To be the devil's advocate, what if your constructor(s) requires you to supply all the members that will/may be required, what issue does that cause?
Also, are you checking the parameters when passed, and throwing informative exceptions?
(The ideological argument of accessor-vs-property is a sidebar. Properties are preferable but I don't think that's the issue with your class design.)

Categories

Resources