Re: [Tutor] python memory management
By: "reference cycles: if one object has a reference to another, and that second object also has a reference to the first, that's a cycle." Is this what you mean? a = 5 b = a a = b I just want to make sure I understand. Thank you very much for your explanation. Monika -- Original Message -- From: Steven D'Aprano To: tutor@python.org Subject: Re: [Tutor] python memory management Date: Fri, 2 Sep 2016 04:10:02 +1000 On Thu, Sep 01, 2016 at 02:12:11PM +, monik...@netzero.net wrote: > Hi: > Can somebody please explain how memory is managed by python? What kind > of memory it uses? What structures use what kind of memory? > If many people work on the same project and have many instances of the > same object how do they ensure that all instances are killed before > the programs exit? Apparently if one of the programmer leaves a > reference to object it might not be automatically deleted by python on > exit. What is the command to do this? > > Could somebody please explain how this works, especially on projects > involving multiple programmers? In general, you (almost) never need to care about memory management, Python will do it for you. The number of programmers writing the code doesn't matter. What matters is how many times the program is running *at the same time*. Each time it runs, your computer's operating system (Windows, Linux, Mac OS X) will start what is called "a process", running the Python interpreter. When the process exits at the end, the OS will reclaim all the memory used and make it available for the next process. While the program is running, the OS has to allocate memory between many different processes. On my computer, right now, I have over 200 processes running. Most of them are handled by the OS, but the others include my email program, my web browser, a few text editors, my desktop manager, and many others. The OS manages the memory allocation. As far as Python is concerned, it manages its own memory from what the OS gives it. When you assign a value: name = "Inigo Montoya" the Python interpreter allocates a chunk of memory in the memory heap to hold the string. It then tracks whether or not the string is being used. So long as the string is being used by your program, or *could possibly* be used, Python will hold onto that string, forever. But as soon as it sees that it can no longer be used, it will free the memory and reuse it. This process is called "garbage collection". You can google for more information, or ask here. Different Python interpreters use different garbage collectors: IronPython uses the .Net garbage collector; Jython uses the Java garbage collector; PyPy has a few different ones that you can choose from; and the CPython (that's the standard Python you are probably running) interpreter has two, a simple "reference counter" GC that works very fast but not very thoroughly, and a more thorough GC that picks up anything the reference counter can't handle. (Mostly reference cycles: if one object has a reference to another, and that second object also has a reference to the first, that's a cycle. The reference counter can't deal with that, but the second GC can.) Let's track the life-span of a chunk of memory. Suppose you write the following code in a module: name = "Inigo Montoya" print(name) name = "The Dread Pirate Roberts" The second assignment frees up the string "Inigo Montoya", as no part of your program can possibly access the old value any more, since it has been replaced by the new value. So the garbage collector frees that chunk of memory and makes it available for something else. This happens automatically, and virtually instantly. You never need to care about allocating or deallocating memory. The interpreter has its own memory manager to do that, with a garbage collector to deallocate memory. So, when do you need to care about memory? - If you are writing a C extension, you have to manage your own memory. - If you're using the ctypes module, you have access to the C code of the interpreter, so you have to care about managing your own memory. - If you're creating massively huge strings or lists, you might have to worry about running out of memory. For example, I once locked up my computer by foolishly creating a HUGE list: # Don't try this at home! L = list(range(100**100)) That would need to find enough memory for a list with one hundred trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion trillion entries. Each entry will take at least four bytes, so the total is ... well, it's a lot. Much more than my poor computer has. On Windows, this will fail quite quickly with a MemoryError, no real harm done, but on Linux (which I use) the OS will gamely, or perhaps stupidly, try very hard to allocate a trillion trill
[Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
Hi Pythonistas What's the correct way to define/access methods of a member variable in a class pointing to an object? For example, I have a class Foo that has a method foo_method: class Foo: def foo_method(self): return 'bar' Now, in another class Bar, I'd like to store an object to this class (I do not want Bar to inherit Foo). What is the correct/recommended way to define class Bar? class Bar: def __init__(self): self.foo = Foo() # OR class Bar: def __init__(self): self.foo = Foo() def bar_method(self): return self.foo.bar() The former will allow me to use: x = Bar() x.foo.foo_method() But, with this I'm directly accessing methods of a member variable (strong coupling). The benefits I see with this approach are: - I don't have to wrap every new method that gets added to class Foo. - Bar may contain more member variables pointing to other classes. Not wrapping them keeps Bar smaller and manageable in size. - The auto-completion facility from IDE (PyCharm, etc.) or IPython helps inspect bar like a menu (x.foo) followed by a sub-menu ( x.foo.foo_method(), x.bar.foobar(), etc.) making it easier to develop code. - Functional programming look-n-feel (not sure if this a pro or con) The cons are strong coupling, not encapsulating internal details of foo, etc. I wanted to check if this a recommended practice? And/or if there are any guidelines related to this (kind of implementing a composite pattern)? There may be more classes (Bat(), etc.) in future and I'd like to extend Foo in future to store an object of these classes. Foo() is a part of a library and my intent is to make Foo() as the entry point for the target users (to allow them auto-completion via dotted notation) rather than having them remember all the classes Bar(), Bat(), etc. Any inputs/pointers will be highly appreciated! Regards Sharad PS> I've posted this in SO at http://stackoverflow.com/questions/39231932/whats-the-correct-way-to-access-methods-of-a-member-variable-in-a-class-pointin/39237874#39237874 but I'm looking for more information/ideas/thoughts/opinions on this. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
On Sat, Sep 03, 2016 at 11:25:07AM +0530, Sharad Singla wrote: > Hi Pythonistas > > What's the correct way to define/access methods of a member variable in a > class pointing to an object? Python recommends that you start with the simplest thing that will work first, which is direct attribute access, and only do something more complex if and when you need to. Python makes it easy to change the implementation without changing the interface! See more comments below. > For example, I have a class Foo that has a method foo_method: > > class Foo: [snip implementation of class Foo] > Now, in another class Bar, I'd like to store an object to this class (I do > not want Bar to inherit Foo). > > What is the correct/recommended way to define class Bar? > > class Bar: > def __init__(self): > self.foo = Foo() Usually this one, with a few exceptions. > The former will allow me to use: > > x = Bar() > x.foo.foo_method() Correct. > But, with this I'm directly accessing methods of a member variable (strong > coupling). This is true, but the warning against coupling is a little more subtle than just "don't do it". The problem is that often you have to duplicate the interface to avoid coupling the *interface* of Bar class to Foo class. Imagine if Foo has, not one method, but fifty: class Bar: def __init__(self): self._foo = Foo() # Keep it private. def bar_method(self): return self._foo.bar_method() def baz_method(self): return self._foo.baz_method() def bing_method(self): return self._foo.bing_method() def spam_method(self): return self._foo.spam_method() def eggs_method(self): return self._foo.eggs_method() def cheese_method(self): return self._foo.cheese_method() ... and so on, for 44 more duplicate methods. At this point, you should ask yourself: what is Bar class adding? It's just a middle-man, which adds complexity to your code and run-time inefficiency. (In Java, middle-man classes still add complexity, but they don't add run-time ineffeciency. The Java compiler can resolve a long chain of dot accesses like: instance.foo.bar.baz.foobar.fe.fi.fo.fum.spam.eggs.cheese.ardvaark_method() into a fast and efficient call direct to ardvaark_method(), but in Python every one of those dots has to be resolved at runtime. You really don't want enormously long chains of dot method calls in Python! A few dots is fine, but don't write Java style.) So middle-man classes have a cost, and they have to pay their way. If they don't pay their way, it is better to dump them, and just work with Foo directly. The same goes for attribute access: you have to weigh up the added complexity of hiding the foo attribute against the benefit gained, and only hide it behind getter and setter methods if you really need to. Python also takes the philosophy that public attributes are usually a good thing. You will often see classes where an attribute is a dict, or a list. For example, in Python 3, there is a class collections.ChainMap which stores a list of dicts. Rather than doing something like this: class ChainMap: def list_sort(self): self._maps.sort() def list_reverse(self): self._maps.reverse() def list_get(self, i): return self._maps[i] # etc. the class just exposes the list directly to the caller. Its a list. You know how to sort lists, and extract items. There's no need to hide it. The interface will never change, it will always be a list. Just access the "maps" attribute, and work with it directly. But generally this applies to relatively simple objects with well-known interfaces, like lists, dicts, and so forth. You might find you have good reason to hide Foo behind a middle-man. Perhaps Foo has a complex, ugly, un-Pythonic interface and you want to provide a more pleasant interface. Or perhaps you want the freedom to change the Foo interface at will, without changing the Bar interface. So while it is *usual* to just do direct attribute access in Python, it is not forbidden to do it the other way. Just make sure you have a good reason, better than "because that's what my Comp Sci 101 professor told me to always do". > The benefits I see with this approach are: > >- I don't have to wrap every new method that gets added to class Foo. >- Bar may contain more member variables pointing to other classes. Not >wrapping them keeps Bar smaller and manageable in size. >- The auto-completion facility from IDE (PyCharm, etc.) or IPython helps >inspect bar like a menu (x.foo) followed by a sub-menu ( >x.foo.foo_method(), x.bar.foobar(), etc.) making it easier to develop >code. >- Functional programming look-n-feel (not sure if this a pro or con) Exactly. That's why Python programmers tend to expose attributes as part of the public interface by default, and only hide them if justified by other concerns. > The cons a
Re: [Tutor] python memory management
monik...@netzero.net wrote: > > By: > "reference cycles: if one object has a reference to another, and > that second object also has a reference to the first, that's a cycle." > > Is this what you mean? > a = 5 > b = a > a = b No. int instances are immutable. The assignments above bind both /names/ a and b to the same instance of int -- 5. The last statement a = b is redundant as a is already bound to 5. For a reference cycle you need something in an object x to refer to another y and vice versa. x and y here are not Python names, but the actual objects. An example using lists: >>> a = ["a"] >>> b = ["b"] Let's append b to a: >>> a.append(b) >>> a[1] ['b'] >>> a[1][1] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range We don't have a cycle yet, so Python eventually complains. Now let's complete the cycle by appending b to a. >>> b.append(a) >>> a[1][1] ['a', ['b', [...]]] >>> a[1][1][1][1][1] ['b', ['a', [...]]] We can keep accessing x[1] forever, and if Python weren't smart enough to detect the cycle instead of producing the [...] it would continue building the string representation for the nested lists until all available memory was consumed or the stack overflowed. Another example with a custom class: >>> class C: ...def __init__(self, name): self.name = name ...def __repr__(self): return self.name ... >>> a = C("a") >>> b = C("b") >>> a a >>> b b >>> a.b = b >>> b.a = a >>> a.b.a.b.a.b.a.b.a.b.a a A cycle may of course consist of more than two objects: >>> a = C("a") >>> b = C("b") >>> c = C("c") >>> a.b = b >>> b.c = c >>> c.a = a >>> c.a.b.c c >>> c.a.b.c.a.b.c.a.b.c c The minimal cycle consists of an object referencing itself: >>> a = C("a") >>> a.a = a >>> a.a.a.a.a.a.a a ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
Hi, Composition is a technique that allows you to express the 'has a' relationship between your object. I'm not a specialist of the OOP but I can see some issues in the model that you expose in your mail. Encapsulation and abstraction are all about designing an API. It allows you to expose simple usable API'S and hiding all the complexity from the user of your classes. If a user have to use your classes in inheritance or composition, he/she doesn't have to worry about the internal details. Wrapping methods of class Foo is a good thing I think. In the case you don't use encapsulation: If Foo is used in Bar, Bat, Baf and after that, the three classes are used anywhere in your code, if you change the API of Foo, you'll end up making changes in all the places where Foo is mentioned! and that's tedious Now, if you use encapsulation The same scenario is not a big deal anymore because you'll end up making less changes than before. That's makes the life easier Abstracting irrelevant details also makes the process of developing easier because you don't have to deal with low level of details to make a code working and helps you to reason about your code in a more efficient way. That techniques lower the level of complexity you have to deal with. I hope that helps a little bit. Regards. Le 3 sept. 2016 10:24, "Sharad Singla" a écrit : > Hi Pythonistas > > What's the correct way to define/access methods of a member variable in a > class pointing to an object? > > For example, I have a class Foo that has a method foo_method: > > class Foo: > def foo_method(self): > return 'bar' > > Now, in another class Bar, I'd like to store an object to this class (I do > not want Bar to inherit Foo). > > What is the correct/recommended way to define class Bar? > > class Bar: > def __init__(self): > self.foo = Foo() > # OR > class Bar: > def __init__(self): > self.foo = Foo() > > def bar_method(self): > return self.foo.bar() > > The former will allow me to use: > > x = Bar() > x.foo.foo_method() > > But, with this I'm directly accessing methods of a member variable (strong > coupling). > > The benefits I see with this approach are: > >- I don't have to wrap every new method that gets added to class Foo. >- Bar may contain more member variables pointing to other classes. Not >wrapping them keeps Bar smaller and manageable in size. >- The auto-completion facility from IDE (PyCharm, etc.) or IPython helps >inspect bar like a menu (x.foo) followed by a sub-menu ( >x.foo.foo_method(), x.bar.foobar(), etc.) making it easier to develop >code. >- Functional programming look-n-feel (not sure if this a pro or con) > > The cons are strong coupling, not encapsulating internal details of foo, > etc. > > I wanted to check if this a recommended practice? And/or if there are any > guidelines related to this (kind of implementing a composite pattern)? > > There may be more classes (Bat(), etc.) in future and I'd like to extend > Foo in future to store an object of these classes. Foo() is a part of a > library and my intent is to make Foo() as the entry point for the target > users (to allow them auto-completion via dotted notation) rather than > having them remember all the classes Bar(), Bat(), etc. > > Any inputs/pointers will be highly appreciated! > > > Regards > > Sharad > > > PS> I've posted this in SO at > http://stackoverflow.com/questions/39231932/whats-the- > correct-way-to-access-methods-of-a-member-variable-in-a- > class-pointin/39237874#39237874 > but I'm looking for more information/ideas/thoughts/opinions on this. > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
On Fri, Sep 2, 2016, at 23:25, monik...@netzero.net wrote: > > By: > "reference cycles: if one object has a reference to another, and > that second object also has a reference to the first, that's a cycle." > > Is this what you mean? > a = 5 > b = a > a = b > > I just want to make sure I understand. > Thank you very much for your explanation. > Monika No, an object that holds reference to other objects is something like a list, tuple, dict. e.g. if you had: a = [] b = [a] a.append(b) you've got two lists, and each one has a reference to the other one. These exist independent of the variables - you could del b and it would still exist in a[0]. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
On 03/09/16 06:55, Sharad Singla wrote: > What's the correct way to define/access methods of a member variable in a > class pointing to an object? Steven has already given you a long and comprehensive answer based on pragmatic python programming. But since you use the term "correct" I'll give you an alternative view based on generic/theoretical OOP practice. The caveat is that theoretical best practice does not always transfer to the real world and you must compromise. Just ensure you compromise in the full knowledge that it is a compromise... The first thing to do is point out that what you are asking about is the Law of Demeter on OOP. See Wikipedia for a full description. In essence it says that the user of an object should not directly access that object's internal attributes/state. So ideally you only access foo via a call to a method of Bar. BUT... that does not mean you should expose all of foo's interface as methods of Bar. After all Bar should only have an instance of Foo to support its own behaviour. In other words whatever methods you call on Bar may manipulate Foo *behind the scenes*. (If Foo is not being used by Foo's methods then what is it doing in Bar at all?!) So if you really want to change some aspect of Bar's Foo instance then it should only be happening as a result of you doing something to your Bar instance. If you really, really need to modify the Foo instance directly (and this should be fairly rare) the "correct" OOP way to do that is for Bar to provide a getFoo() accessor method and for you to fetch the Foo instance and then manipulate it directly b = Bar() f = b.getFoo() f.someMethod() f.someAttribute = 42 # etc... b.setFoo(f) # put it back when you are done. This then keeps Bar's use of foo hidden (you don't know if Bar is returning a reference to its internal Foo or creating a copy for you to play with.) In python we tend to use direct access rather than getFoo/setFoo. We'd just say b.foo, but that means if Bar wants to return a copy of Foo then it needs to implement foo as a property. So to summarise, the Law of Demeter states that you should provide foo access via Bar's interface but the expectation is that you only create operations(methods) on Bar that modify Foo as a part of that operation, not that you simply expose all of Foo via Bar. One huge exception to all of this is where you create Bar explicitly as a manager of Foo objects and its role is only to provide access to Foos (an example might be an object pool in a server application). But in that case there probably should be get/set methods which will do some sanity checking before handing over a Foo to you to play with, or storing a foo that you have been messing about with. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
On 03/09/16 04:25, monik...@netzero.net wrote: > Is this what you mean? > a = 5 > b = a > a = b No, you are confusing variable names with objects. Here you only have one object - the number 5. For a cycle you need at least 2 objects and those objects must be able to reference another object. In practice that means a collection or an instance of a class. a = [] b = [a] a.append(b) The two lists are now cyclically referring to each other. We can now delete the names a and b and the two list objects will continue to exist in memory even though no variables refer to them. This is where the second garbage collector comes into play, it can recognise the link between the lists and the fact that no variable refers to them. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
On Thu, Sep 01, 2016 at 08:21:36PM +, monik...@netzero.net wrote: > Thank you for your explanation. It is very clear and confirms what I > thought I knew. However, I had a job interview and the interview said > it was a mistake that I did not say that in cases when there are > multiple programmers, there might be some objects/references left and > not deallocated from the memory by python. He asked me how this should > be handles. Without being there, I cannot be sure precisely what he meant. But frankly it sounds like the interviewer doesn't know what he is talking about. The number of programmers who work on a project has nothing to do with how it manages memory. Whether you have one person who writes the code, or a hundred people writing the code, memory is managed exactly the same way. Perhaps you misunderstood the question, or perhaps the interviewer simply wasn't as knowledgable or smart as he thought he was. > So I told him that python has its automatic garbage collection which > keeps track of all objects and references and deletes them as > appropriate (similar what you state). I added that programmers can > keep track of occurrences of object and make sure that it goes down to > 0. And if it does not then use del to delete. However, he did not like > my answer. What you say is technically correct, but if you find yourself using del more than very occasionally, I suggest that you need to think hard about what you are doing. It is not normally necessary to use del. > So Im trying to learn from my mistakes and learn if an > object or reference are still at the end of the program how they > should be deleted. A thought comes to mind... When Python shuts down, it has to deallocate all your remaining objects, giving them a chance to run any finaliser methods. But sometimes the finaliser methods don't get to run until Python has already deallocated the global variables, including modules you might want to use. So for example: import math class Widget: def __del__(self): # Finaliser print(math.sin(10)) but if your widget doesn't get deallocated until the end of your application, it may be that math has been set to None and math.sin is no longer available. Perhaps he was asking about that? What sort of job were you asking for? I expect that would be counted as an extremely advanced corner of Python, not something that most people know or need to know. > I had problem understanding him too well since he > was calling from overseas (there was interference) and I could not > understand his accent well. But I need to learn this for future > interviews. > > Your posting states that this is not a problem but according to the > interviewer it is. (I do not mean to be un-nice to you, sorry) So how > this situation should be handled? There's no way to know the right way. Some interviewers think they know more than they actually do. When you tell them the right answer, they think it is wrong because they are ignorant. Some interviewers are deliberately testing you with really obscure, complex corners of the language. Maybe he was right, and there is some tiny corner where what I told you was incorrect. Maybe you misunderstood the question. Maybe the interviewer was deliberately testing you with false information, to see what you would do. Would you argue with him? Get frustrated? Agree with him even if you knew the answer was actually wrong? There's no way of knowing what they are looking for. Do they want people who will push back and stand their ground when they know they are right, or people who will be good little employees who will agree when the boss says that milk is purple and England is the capital of China? I guess the only thing you can do is answer as best you can, ask for clarifications, and hope. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python projects
On Thu, Sep 01, 2016 at 05:35:33AM +, monik...@netzero.net wrote: > Hi: > I have been taking python classes for overa year now and studying and > studying it all days long. However, I still cannot get a job as a > python automation qa (despite of many years of experience in qa) > because everybody is looking for a senior python developers for > automation qa jobs. Entry level positions are rare. Is there a website > where I could maybe do some python projects for somebody, for free or > for low pay? Pretty soon I will have to take a survival job since my > savings are ending and when that happens I will not have much time to > practice python and all my hard work will go to waste. I really, really feel sympathy for you. I think that a lot of people are in situations like yours. I am lucky enough to have a job that gives me time to practice Python, but that is the silver lining in a dark cloud: I have time to practice Python because I only work part time (not by choice). Very occasionally I get to use my Python skills as part of my work, but not often. So I share your pain. I'll be honest, I'm not sure what software QA is supposed to do, or what skills you have, so I'll have to guess. I don't know of any *paid* Python projects looking with entry-level QA positions, I am sorry, but you might consider helping with some open-source projects or even the Python language itself. The work is unpaid, but you can list it on your CV and gain experience. Pick some open-source Python projects run by volunteers, and see if they need help with testing and QA. Most small projects need help with testing and documentation -- there are lots of programmers who can write code but are no good (or, let's be honest, too lazy) to write tests and documentation. Do you have lots of experience with a testing framework like Nose? Maybe you can volunteer to work on the framework, and get some skills and useful contacts and something to put on your CV. Again, as these projects are all run by volunteers, there is unlikely to be any pay for it. Or look at the Python bug tracker: http://bugs.python.org/ Can you find some issues that you can work on? Bugs that you can fix? Find issues that are waiting for tests and write some tests, and put them on the bug tracker. As a beginner, expect that senior developers will want to check your work. Sometimes they are extremely busy and patches languish in the bug tracker, waiting for somebody to review them. More about contributing to Python here: https://docs.python.org/devguide/#contributing Don't forget the Job Board: https://jobs.python.org/ And good luck! -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
On Sat, Sep 03, 2016 at 02:51:22PM +0100, Alan Gauld via Tutor wrote: [...] > The first thing to do is point out that what you > are asking about is the Law of Demeter on OOP. > See Wikipedia for a full description. In essence > it says that the user of an object should not > directly access that object's internal attributes/state. > So ideally you only access foo via a call to a method of > Bar. That's a very important answer too, thanks Alan for reminding me of it, but remember that the Law of Demeter is more of a guideline, and we should understand it, not just blindly quote it. One classic example of the Law Of Demeter is: "If you want your dog to come to you, don't talk to your dog's legs, talk to the dog." class Dog: ... fido = Dog() # I want the dog to come here. fido.left_front_leg.lift() fido.left_front_leg.forward() fido.left_front_leg.down() fido.right_back_leg.lift() ... Arggh, no, that's terrible! That violates the Law Of Demeter, and you shouldn't expect your users to do that. The caller shouldn't have to care about *how the dog walks*. fido.command("come here boy!") Or perhaps: fido.heel() whatever is most appropriate. The details of how the dog walks is encapsulated inside the Dog class. Another classic example is of a transaction where the paper boy gives you a newspaper and you pay him a dollar: newspaper = paperboy.get_paper() paperboy.balance += 1.0 customer.trousers.wallet.balance -= 1.0 No! Would you really let the paperboy reach into your trousers, grab your wallet, open it up, and take money out? Again, another Demeter violation. Better to re-write your Customer class: class Customer: def pay(self, amount): if amount > self.wallet.balance: raise ValueError self.wallet.balance -= amount return amount paperboy.receive(customer.pay(1.0)) But sometimes the Law Of Demeter should not apply. Sometimes you are expected to tinker with the internals of an object. car = Car() # replace the engine with a bigger one car.engine = Engine("800 horsepower of throbbing nitro-fueled POWER") car.engine.inject(nitro=True) but as I suggested in an earlier email, that mostly applies when the attribute is a fairly simple object like a list, a dict, or similar. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
On 03/09/16 18:17, Steven D'Aprano wrote: > One classic example of the Law Of Demeter is: > > "If you want your dog to come to you, don't talk to your dog's legs, > talk to the dog." I love that, I've never seen it before but a great example. > But sometimes the Law Of Demeter should not apply. Sometimes you are > expected to tinker with the internals of an object. > > car = Car() > # replace the engine with a bigger one > car.engine = Engine("800 horsepower of throbbing nitro-fueled POWER") > car.engine.inject(nitro=True) Yep, although in that case I'd take the engine "out of the car" engine = car.engine engine.inject() car.engine = engine Of course in python(or Java) the last line is usually not needed because we work with references to the real object rather than copies... Its not necessary to get the extra reference but for me I like the code to reflect the intent as well as the need. So by creating an external reference to the engine it reminds me that I am tinkering with a different object to the car. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] 'int' object has no attribute 'items'
Hello,Am trying to solve a problem, but keep getting different errors. Country X calculates tax for its citizens using a graduated scale rate as shown below: - Yearly Income: 0 - 1000Tax Rate: 0% - Yearly Income: 1,001 - 10,000Tax Rate: 10% - Yearly Income: 10,001 - 20,200Tax Rate: 15% - Yearly Income: 20,201 - 30,750Tax Rate: 20% - Yearly Income: 30,751 - 50,000Tax Rate: 25% - Yearly Income: Over 50,000Tax Rate: 30% Am trying to write a Python function that will calculate tax rate. def calculate_tax(dict_inp): result = {} if dict_inp == {}: result = "Please enter valid inputs" else: for k, v in dict_inp.items(): try: x = int(dict_inp[k]) except ValueError: print("That's not an int!") break if(x): if x > 5: tax = ((x - 5) * 0.3) + 4812.5 + 2110 + 1530 + 900 result[k] = tax elif x > 30750: tax = ((x - 30750) * 0.25) + 2110 + 1530 + 900 result[k] = tax elif x > 20200: tax = ((x - 20200) * 0.2) + 1530 + 900 result[k] = tax elif x > 1: tax = ((x - 1) * 0.15) + 900 result[k] = tax elif x > 1000: tax = ((x - 1000) * 0.1) result[k] = tax else: tax = 0 result[k] = tax else: print("Yearly income is not an integer") return result dict_inp = {'Alex': 500,'James': 20500,'Kinuthia': 7}#dict_inp = {200: 1500,300: 20500,400: 7}print(calculate_tax(dict_inp)) But I get the result: THERE IS AN ERROR/BUG IN YOUR CODE Results: Internal Error: runTests aborted: TestOutcomeEvent(handled=False, test=, result=, outcome='error', exc_info=(, AttributeError("'int' object has no attribute 'items'",), ), reason=None, expected=False, shortLabel=None, longLabel=None) is not JSON serializable{'James': 2490.0, 'Alex': 0, 'Kinuthia': 15352.5} But when i take away the .items(), i get: for k, v in dict_inp: ValueError: too many values to unpack Please I need help.I am using windows 10, python 3.5.2, Thanks ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
So what does [...] mean? -- Original Message -- From: Peter Otten <__pete...@web.de> To: tutor@python.org Subject: Re: [Tutor] python memory management Date: Sat, 03 Sep 2016 14:26:12 +0200 monik...@netzero.net wrote: > > By: > "reference cycles: if one object has a reference to another, and > that second object also has a reference to the first, that's a cycle." > > Is this what you mean? > a = 5 > b = a > a = b No. int instances are immutable. The assignments above bind both /names/ a and b to the same instance of int -- 5. The last statement a = b is redundant as a is already bound to 5. For a reference cycle you need something in an object x to refer to another y and vice versa. x and y here are not Python names, but the actual objects. An example using lists: >>> a = ["a"] >>> b = ["b"] Let's append b to a: >>> a.append(b) >>> a[1] ['b'] >>> a[1][1] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range We don't have a cycle yet, so Python eventually complains. Now let's complete the cycle by appending b to a. >>> b.append(a) >>> a[1][1] ['a', ['b', [...]]] >>> a[1][1][1][1][1] ['b', ['a', [...]]] We can keep accessing x[1] forever, and if Python weren't smart enough to detect the cycle instead of producing the [...] it would continue building the string representation for the nested lists until all available memory was consumed or the stack overflowed. Another example with a custom class: >>> class C: ...def __init__(self, name): self.name = name ...def __repr__(self): return self.name ... >>> a = C("a") >>> b = C("b") >>> a a >>> b b >>> a.b = b >>> b.a = a >>> a.b.a.b.a.b.a.b.a.b.a a A cycle may of course consist of more than two objects: >>> a = C("a") >>> b = C("b") >>> c = C("c") >>> a.b = b >>> b.c = c >>> c.a = a >>> c.a.b.c c >>> c.a.b.c.a.b.c.a.b.c c The minimal cycle consists of an object referencing itself: >>> a = C("a") >>> a.a = a >>> a.a.a.a.a.a.a a ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor howlifeworks.com (Sponsored by Content.Ad) Why Women Are Flocking to This Incredible New Shopping Site http://thirdpartyoffers.netzero.net/TGL3241/57cb3e00e29ee3e000c94st01duc ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What's the correct way to define/access methods of a member variable in a class pointing to an object?
@Steven, @Khalil, @Alan Thanks for the inputs/explanations. Appreciate it! Regards Sharad ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
Is there any practical usage of using reference cycling? On Sat, 2016-09-03 at 14:56 +0100, Alan Gauld via Tutor wrote: > On 03/09/16 04:25, monik...@netzero.net wrote: > > > > > Is this what you mean? > > a = 5 > > b = a > > a = b > > No, you are confusing variable names with objects. > Here you only have one object - the number 5. > For a cycle you need at least 2 objects and those > objects must be able to reference another object. > In practice that means a collection or an instance > of a class. > > a = [] > b = [a] > a.append(b) > > The two lists are now cyclically referring to each > other. We can now delete the names a and b and > the two list objects will continue to exist > in memory even though no variables refer to them. > This is where the second garbage collector comes > into play, it can recognise the link between the > lists and the fact that no variable refers to them. > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
On 03/09/16 22:16, monik...@netzero.net wrote: > So what does [...] mean? Its Python's way of telling you that you have a self referential data structure. Its just a representational thing but without it Python would end up printing an infinite sequence of values. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] python memory management
On 03/09/16 23:20, zakaria wrote: > Is there any practical usage of using reference cycling? There are a (very) few cases where data structures require the creation of cyclic references. One example I've used is in managing comms networks where nodes are multiply and/or cyclically linked and you need to build those linkages into your data model. In those cases you need to manage the cleanup yourself. But most cyclic references occur by accident, the programmer probably didn't intend them to exist but it just so happened that one object points to another which happens to point at another which in turn points at the first. The cycle can span many objects. Think of a directory tree where a deeply nested node has a link pointing back at a root level node. But the root also indirectly points at that low level node by means of the tree structure... As a specific example, It often happens in GUIs where widgets hold references to other widgets higher in the widget parent/child tree. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] 'int' object has no attribute 'items'
Hi Chidinma, I'm afraid it is very difficult for me to understand your code, because your email program (Yahoo mail perhaps?) has mangled the code and put it all on one single line: On Sat, Sep 03, 2016 at 09:45:17PM +, Chidinma via Tutor wrote: > def calculate_tax(dict_inp): result = {} if dict_inp == {}: result = > "Please enter valid inputs" else: for k, v in dict_inp.items(): try: > x = int(dict_inp[k]) except ValueError: print("That's not > an int!") break if(x): if x > 5: tax = ((x - > 5) * 0.3) + 4812.5 + 2110 + 1530 + 900 result[k] = tax > elif x > 30750: tax = ((x - 30750) * 0.25) + 2110 + 1530 + 900 > result[k] = tax elif x > 20200: tax = ((x - 20200) * 0.2) > + 1530 + 900 result[k] = tax elif x > 1: tax = > ((x - 1) * 0.15) + 900 result[k] = tax elif x > 1000: > tax = ((x - 1000) * 0.1) result[k] = tax else: > tax = 0 result[k] = tax else: print("Yearly income is > not an integer") return result dict_inp = {'Alex': 500,'James': > 20500,'Kinuthia': 7}#dict_inp = {200: 1500,300: 20500,400: > 7}print(calculate_tax(dict_inp)) You may be able to prevent that by turning of "formatted text", or "rich text", or "HTML email", or whatever your email program calls this feature. > But I get the result: > > THERE IS AN ERROR/BUG IN YOUR CODE How are you running this? Python doesn't normally print "THERE IS AN ERROR/BUG IN YOUR CODE". My guess is that you are using one of the on-line Python courses where you type your code into the web page. Am I right? Which one? > Results: Internal Error: runTests aborted: TestOutcomeEvent(handled=False, > test=, result=, outcome='error', exc_info=(, AttributeError("'int' object has > no attribute 'items'",), ), reason=None, expected=False, shortLabel=None, > longLabel=None) is not JSON serializable{'James': 2490.0, 'Alex': 0, > 'Kinuthia': 15352.5} That error doesn't seem to have anything to do with your code. Are you sure it is connected to the code you give above? If you are using a website, it might be a bug in the website. > But when i take away the .items(), i get: > for k, v in dict_inp: > ValueError: too many values to unpack The first thing to confirm that dict_inp is a dict. Run: print( isinstance(dict_inp, dict) ) just before that "for ..." line. If it prints True, then change the for line to: for k, v in dict_inp.items(): What happens then? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor