Re: [Tutor] class functions/staticmethod?
On 14Aug2019 11:15, Steven D'Aprano wrote: On Wed, Aug 14, 2019 at 09:58:35AM +1000, Cameron Simpson wrote: On 11Aug2019 22:58, James Hartley wrote: >I am lacking in understanding of the @staticmethod property. >Explanation(s)/links might be helpful. I have not found the descriptions >found in the Internet wild to be particularly instructive. You have received some answers; to me they seem detailed enough to be confusing. Its only confusing if you don't work your way through it carefully and systematically. There's a lot to understand, but if you don't understand it, Python's behaviour in this case seems counter-intuitive and hard to follow. Yeah, but it helps to understand the objective: function context. A deep dive into the mechanisms used to achieve that is a load to ingest. High levels of detail tend to swamp one's view of the larger picture, particularly when learning. [...] I think of things this way: what context does a method require? Not everything needs the calling instance. Here endeth the lesson. Given that you go on to write almost another 150 lines of explanation, I think a better description would be "Here *begins* the lesson" *wink* Well, maybe, but I really wanted to highlight the objective: @classmethod and @staticmethod dictate the context provided to the method. All the examples that follow aim, however vaguely, to show those contexts in action. Your lesson, I think, assumes that it is obvious that staticmethods don't have access to the calling instance, or its class. No, it aims to make that point clear. EVerything else is example or mechanism. But if you look at James' code, I think you will agree that he's assuming that staticmethods *do* have access to the calling class, and is perplexed by the fact that the look-up of class variables (class attributes) fails. Because nobody had said that @staticmethod and @classmethod _define_ the provided context. Your lesson gives us no clue why James' first method, "dimensions()", which he describes as a "class method", isn't a class method and doesn't actually work correctly, even though it appears to at first glance. I didn't try to tackle his code. I think it is better to get the intended use of @classmethod and @staticmethod clear. Digging into whatever weird consequences there might be to his slightly wrong code just brings confusion. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class functions/staticmethod?
On Wed, Aug 14, 2019 at 09:58:35AM +1000, Cameron Simpson wrote: > On 11Aug2019 22:58, James Hartley wrote: > >I am lacking in understanding of the @staticmethod property. > >Explanation(s)/links might be helpful. I have not found the descriptions > >found in the Internet wild to be particularly instructive. > > You have received some answers; to me they seem detailed enough to be > confusing. Its only confusing if you don't work your way through it carefully and systematically. There's a lot to understand, but if you don't understand it, Python's behaviour in this case seems counter-intuitive and hard to follow. Python makes the behaviour of regular instance methods so simple and intuitive, it can be quite a blow when you try to do something that isn't. > I think of things this way: what context does a method require? Not > everything needs the calling instance. > > Here endeth the lesson. Given that you go on to write almost another 150 lines of explanation, I think a better description would be "Here *begins* the lesson" *wink* Your lesson, I think, assumes that it is obvious that staticmethods don't have access to the calling instance, or its class. But if you look at James' code, I think you will agree that he's assuming that staticmethods *do* have access to the calling class, and is perplexed by the fact that the look-up of class variables (class attributes) fails. If James comes from a Java background, he's probably assuming that static methods do have access to the class variables, using undotted names: class K(object): attr = 1 @staticmethod def foo(): return attr In Java, K.foo() would return 1. Your lesson gives us no clue why James' first method, "dimensions()", which he describes as a "class method", isn't a class method and doesn't actually work correctly, even though it appears to at first glance. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class functions/staticmethod?
On 11Aug2019 22:58, James Hartley wrote: I am lacking in understanding of the @staticmethod property. Explanation(s)/links might be helpful. I have not found the descriptions found in the Internet wild to be particularly instructive. You have received some answers; to me they seem detailed enough to be confusing. I think of things this way: what context does a method require? Not everything needs the calling instance. Here endeth the lesson. All this stuff below is examples based on that criterion: Here's a trite example class: class Rectangle: def __init__(self, width, height): self.width=width self.height = height Most methods do things with self, and are thus "instance methods", the default. They automatically receive the instance used to call them as the first "self" argument. def area(self): return self.width * self.height They need "self" as their context to do their work. Some methods might not need an instance as context: perhaps they return information that is just based on the class, or they are factory methods intended to return a new instance of the class. Then you might use a @classmethod decorator to have the calling instance's class as the context. @classmethod def from_str(cls, s): width, height = parse_an_XxY_string(s) return cls(width, height) And some methods do not need the class or the instance to do something useful: @staticmethod def compute_area(width, height): return width * height and so we don't give them the instance or the class as context. Now, _why_? Instance methods are obvious enough - they exist to return values without the caller needing to know about the object internals. Class methods are less obvious. Consider that Python is a duck typed language: we try to arrange that provided an object has the right methods we can use various different types of objects with the same functions. For example: def total_area(flat_things): return sum(flat_thing.area() for flat_thing in flat_things) That will work for Rectangles and also other things with .area() methods. Area, though, is an instance method. Class methods tend to come into their own with subclassing: I particularly use them for factory methods. Supposing we have Rectangles and Ellipses, both subclasses of a FlatThing: class FlatThing: def __init__(self, width, height): self.width=width self.height = height @classmethod def from_str(cls, s): width, height = parse_an_XxY_string(s) return cls(width, height) class Rectangle(FlatThing): def area(self): return self.width * self.height class Ellipse(FlatThing): def area(self): return self.width * self.height * math.PI / 4 See that from_str? It is common to all the classes because they can all be characterised by their width and height. But I require the class for context in order to make a new object of the _correct_ class. Examples: rect = Rectangle.from_str("5x9") ellipse = Ellipse.from_str("5x9") ellispe2 = ellipse.from_str("6x7") Here we make a Rectangle, and "cls" is Rectangle when you call it this way. Then we make an Ellipse, and "cls" is Ellipse when called this way. And then we make another Ellipse from the first ellipse, so "cls" is again "Ellipse" (because "ellipse" is an Ellipse). You can see that regardless of how we call the factory function, the only context passed is the relevant class. And in the last example (an Ellipse from an existing Ellipse), the class comes from the instance used to make the call. So we can write some function which DOES NOT KNOW whether it gets Ellipses or Rectangles: def bigger_things(flat_things): return [ flat_thing.from_str( "%sx%s" % (flat_thing.width*2, flat_thing.height*2)) for flat_thing in flat_things ] Here we could pass in a mix if Rectangles or Ellipses (or anything else with a suitable from_str method) and get out a new list with a matching mix of bigger things. Finally, the static method. As Peter remarked, because a static method does not have the instance or class for context, it _could_ be written as an ordinary top level function. Usually we use a static method in order to group top level functions _related_ to a specific class together. It also helps with imports elsewhere. So consider the earlier: @staticmethod def compute_area(width, height): return width * height in the Rectangle class. We _could_ just write this as a top level function outside the class: def compute_rectangular_area(width, height): return width * height Now think about using that elsewhere: from flat_things_module import Rectangle, Ellipse, compute_rectangular_area area1 = compute_rectangular_area(5, 9) area2 = Rectangle.compute_area(5, 9) area3 = Ellipse.compute_area(5, 9) I would rather use the forms of "area2" and "area3" because it is clear that I'm getting an area function from a nicely named class.
Re: [Tutor] class functions/staticmethod?
Part 3. On Sun, Aug 11, 2019 at 10:58:37PM -0500, James Hartley wrote: > from collections import namedtuple > > class Foo(): > Dimensions = namedtuple('Dimensions', ['height', 'width']) > _dimensions = Dimensions(3, 4) > > def dimensions(): > print('id = {}'.format(id(Foo._dimensions))) > return Foo._dimensions > > @staticmethod > def dimensions1(): > print('id = {}'.format(id(_dimensions))) > return _dimensions In part 2, I explained that we can re-write the dimensions() method to work correctly using the @classmethod decorator: @classmethod def dimensions(cls): print('id = {}'.format(id(cls._dimensions))) return cls._dimensions Another benefit of doing this is that it will now work correctly in subclasses. class Bar(Foo): # inherit from Foo _dimensions = (3, 4, 5, 6) # Override the parent's "dimensions". Using your definition, Bar.dimensions() will return Foo._dimensions instead of Bar._dimensions. But using the classmethod version works as expected. So why doesn't the staticmethod version work correctly? Its all to do with the way variable names are resolved by the interpreter. If you are used to Java, for example, you might expect that "class variables" (what Python calls "class attributes") are part of the scope for methods: spam = 999 # Global variable spam. class MyClass(object): spam = 1 # Class attribute ("variable") spam. def method(self): return spam instance = MyClass() If you are used to Java's rules, you would expect that instance.method() will return 1, but in Python it returns the global spam, 999. To simplify a little, the scoping rules for Python are described by the LEGB rule: - Local variables have highest priority; - followed by variables in the Enclosing function scope (if any); - followed by Global variables; - and lastly Builtins (like `len()`, `zip()`, etc). Notice that the surrounding class isn't included.[1] To access either instance attributes or class attributes, you have to explicitly say so: def method(self): return self.spam This is deliberate, and a FAQ: https://docs.python.org/3/faq/design.html#why-must-self-be-used-explicitly-in-method-definitions-and-calls Using Java's scoping rules, the staticmethod would have worked: @staticmethod def dimensions1(): print('id = {}'.format(id(_dimensions))) return _dimensions because it would see the _dimensions variable in the class scope. But Python doesn't work that way. You would have to grab hold of the class from the global scope, then grab dimensions: @staticmethod def dimensions1(): _dimensions = Foo._dimensions print('id = {}'.format(id(_dimensions))) return _dimensions If you are coming from a Java background, you may have been fooled by an unfortunate clash in terminology. A "static method" in Java is closer to a *classmethod* in Python, not a staticmethod. The main difference being that in Java, class variables (attributes) are automatically in scope; in Python you have to access them through the "cls" parameter. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class functions/staticmethod?
James Hartley wrote: > I am lacking in understanding of the @staticmethod property. > Explanation(s)/links might be helpful. I have not found the descriptions > found in the Internet wild to be particularly instructive. Given the code > below: > =8<-- > from collections import namedtuple > > class Foo(): > Dimensions = namedtuple('Dimensions', ['height', 'width']) > _dimensions = Dimensions(3, 4) > > def dimensions(): > print('id = {}'.format(id(Foo._dimensions))) > return Foo._dimensions That works with the class as Foo.dimensions is just a function in Python 3, but not with an instance because Python will try to pass the instance as the first argument >>> Foo.dimensions() id = 140192821560880 Dimensions(height=3, width=4) >>> Foo().dimensions() Traceback (most recent call last): File "", line 1, in TypeError: dimensions() takes 0 positional arguments but 1 was given You can turn it into a static method @staticmethod def dimensions(): print('id = {}'.format(id(Foo._dimensions))) return Foo._dimensions >>> Foo.dimensions() id = 139629779179056 Dimensions(height=3, width=4) >>> Foo().dimensions() id = 139629779179056 Dimensions(height=3, width=4) or, when you are planning for subclases, into a classmethod: $ cat staticmethod_demo.py class Foo(): _dimensions = "foo-dimensions" @classmethod def class_dimensions(cls): return cls._dimensions @staticmethod def static_dimensions(): return Foo._dimensions class Bar(Foo): _dimensions = "bar-dimensions" $ python3 -i staticmethod_demo.py >>> Foo.class_dimensions(), Foo.static_dimensions() ('foo-dimensions', 'foo-dimensions') >>> Bar.class_dimensions(), Bar.static_dimensions() ('bar-dimensions', 'foo-dimensions') > > @staticmethod > def dimensions1(): > print('id = {}'.format(id(_dimensions))) > return _dimensions > =8<-- > The class method Foo.dimensions() is capable of accessing class members, > but Foo.dimensions1() cannot. What does the @staticmethod decorator really > add? You do not really need static methods; they work like module-level functions. They are more of a means to organize your code; by writing class Foo: @staticmethod def bar(...): do stuff instead of def foo_bar(...): do stuff class Foo: pass you make the mental association between the class and the function a bit stronger. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class newbie
thanks! On Sun, Jul 23, 2017 at 5:35 PM, Danny Yoowrote: > On Sun, Jul 23, 2017 at 1:24 PM, Michael C > wrote: > > class mahschool: > > def print(): > > print('Say something') > > > By the way, you've chosen a name for your method that's spelled the > same as the name of the built-in "print" function. I'd recommend you > choose a different name than "print" in your method name, just to > avoid any potential confusion. This isn't going to solve the > immediate problem that you encountered and solved: you figured out > that methods need to have a self argument. But you probably still > want to rename to avoid the name collision. > > > Good luck! > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class newbie
On 07/23/2017 02:42 PM, Michael C wrote: > never mind, I forgot to put 'self' in the method definition! class mahschool: def print(self): print('Say something') a = mahschool() a.print() Indeed. The error message was clear on this - but not in a way that's always instructive until you're used to it :) "TypeError: print() takes 0 positional arguments but 1 was given" A method is called "silently" (you didn't pass it yourself as an argument when you called print()) with the instance, so you need to declare such a parameter in the method definition. And to give myself an excuse for preaching: it's usually not a great idea to reuse the name of a built-in function. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class newbie
On Sun, Jul 23, 2017 at 1:24 PM, Michael Cwrote: > class mahschool: > def print(): > print('Say something') By the way, you've chosen a name for your method that's spelled the same as the name of the built-in "print" function. I'd recommend you choose a different name than "print" in your method name, just to avoid any potential confusion. This isn't going to solve the immediate problem that you encountered and solved: you figured out that methods need to have a self argument. But you probably still want to rename to avoid the name collision. Good luck! ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class newbie
never mind, I forgot to put 'self' in the method definition! class mahschool: def print(self): print('Say something') a = mahschool() a.print() On Sun, Jul 23, 2017 at 1:24 PM, Michael Cwrote: > class mahschool: > def print(): > print('Say something') > > > a = mahschool() > > a.print() > > > > With this, I get this error: > > Traceback (most recent call last): > File "test.py", line 8, in > a.print() > TypeError: print() takes 0 positional arguments but 1 was given > > > What did I do wrong? > > Thanks! > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class
On 20/06/17 23:39, Rex Florian via Tutor wrote: > Can someone explain how Python achieves the vector addition of more than 2 > vectors > without some kind of looping? > > class Vector: >def __init__(self, a, b): >def __str__(): >def __add__(self,other): > return Vector(self.a + other.a, self.b + other.b) > print(v1 + v2 + v3) When you do the addition Python evaluates it from left to right so it is interpreted as: ((v1+v2) + v3) so Python does: v1.__add__(v2) Which returns a new vector, let's call it vt Python then does: vt.__add__(v3) which returns another new vector, lets call it result, which is what gets printed using print (result.__str__()) -- 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] Class Inheritance
Rafael Knuth wrote: > Hey there, > > I am trying to wrap my head around Class Inheritance in Python, and I > wrote a little program which is supposed to calculate revenues from > customers who don't get a discount (parent class) and those who get a > 30% discount (child class): > > class FullPriceCustomer(object): > def __init__(self, customer, rate, hours): > self.customer = customer > self.rate = rate > self.hours = hours > > print ("Your customer %s made you %s USD this year." % > (customer, rate * hours)) > > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > print ("Your customer %s made you %s USD at a 30% discount > rate this year." % (self.customer, self.rate * rate * discount)) > > customer_one = DiscountCustomer("Customer A", 75, 100) > customer_two = FullPriceCustomer("Customer B", 75, 100) > > The DiscountCustomer class instance gets me the wrong result (it does > not calculate the discount) and I was not able to figure out what I > did wrong here. > Can anyone help? Thanks! In a real application you would not introduce two classes for this -- a FullPriceCustomer would be a customer with a discount of 0%. Then you mix output with initialisation, so let's fix that first: class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.rate * self.hours) ) customer = FullPriceCustomer("Customer B", 75, 100) customer.print_summary() Now look at your code: what has to change for a customer who gets a discount? self.rate * self.hours will become self.discount * self.rate * self.hours or as I prefer to store the part that the customer doesn't pay as the discount (1 - self.discount) * self.rate * self.hours To make overriding easy we put that calculation into a separate method: class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.get_total()) ) def get_total(self): return self.rate * self.hours customer = FullPriceCustomer("Customer B", 75, 100) customer.print_summary() Then the DiscountCustomer class can be written class FullPriceCustomer(object): def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print( "Your customer %s made you %s USD this year." % (self.customer, self.get_total()) ) def get_total(self): return self.rate * self.hours class DiscountCustomer(FullPriceCustomer): discount = 0.3 def get_total(self): return (1 - self.discount) * self.rate * self.hours customers = [ DiscountCustomer("Customer A", 75, 100), FullPriceCustomer("Customer B", 75, 100), ] for customer in customers: customer.print_summary() If we run that we see that the calculation may be correct, but the discount is not mentioned. We could solve this by overriding print_summary, but here's another way: class FullPriceCustomer(object): summary_template = ( "Your customer {0.customer} made you {0.total} USD this year." ) def __init__(self, customer, rate, hours): self.customer = customer self.rate = rate self.hours = hours def print_summary(self): print(self.summary_template.format(self)) @property def total(self): return self.rate * self.hours class DiscountCustomer(FullPriceCustomer): summary_template = ( "Your customer {0.customer} made you {0.total} USD " "at a {0.discount:.0%} this year." ) discount = 0.3 @property def total(self): return (1 - self.discount) * self.rate * self.hours class VIC(DiscountCustomer): discount = 0.33 customers = [ DiscountCustomer("Customer A", 75, 100), FullPriceCustomer("Customer B", 75, 100), VIC("Customer C", 75, 100), ] for customer in customers: customer.print_summary() If one day you choose to use an isinstance check to see if you have a FullPriceCustomer for customer in customers: if isinstance(customer, FullPriceCustomer): print(customer.customer, "pays the full price") you may be surprised to see that all customers seem to be paying the full price. That's because isinstance(obj, class_) is true even if the actual class of obj is a subclass of class_. Therefore I recommend that you change your class hierarchy to class Customer(object): ... class FullPriceCustomer(Customer): ...
Re: [Tutor] Class Inheritance
On 21/02/17 09:49, Rafael Knuth wrote: > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > print ("Your customer %s made you %s USD at a 30% discount > rate this year." % (self.customer, self.rate * rate * discount)) I meant to add... are you sure that calculation is what you meant? First point is that discount is not defined, you need to prefix it with either self or DiscountCustomer. But also, it doesn't use hours? Is that correct? -- 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] Class Inheritance
On 21/02/17 09:49, Rafael Knuth wrote: > class FullPriceCustomer(object): > def __init__(self, customer, rate, hours): > > > class DiscountCustomer(FullPriceCustomer): > discount = 0.7 > def calculate_discount(self, rate, hours): > > customer_one = DiscountCustomer("Customer A", 75, 100) > customer_two = FullPriceCustomer("Customer B", 75, 100) You create two instances and as such the FullPriceCustomer.__init__() method gets executed in both cases. This is because the subclass does not provide an __init__() of its own, so the inherited one is used. Your discount is calculated in the calculate_discount() method, but that is never called. If you added a line: customer_one.calculate_discount(75,100) you would see the discount appear. Alternatively create an init() for your subclass that calls the superclass init() then calls self.calculate_discount(rate,hours) BTW It's bad practice to mix calculations and display(print) in the same method, it's better to separate them, but that's probably a topic for another thread Get the inheritance sorted first :-) -- 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] Class learning
On 23/01/15 01:44, jarod...@libero.it wrote: How can gave the attributes __name__ to a function? You don't Python does it for you. class Foo(object): def __init__(self): steps = {} tmp = open(rnaseq.base.ini,rb) config.readfp(tmp) readsets = parse_illumina_readset_file(/home/mauro/Desktop/readset.csv) You realise that steps is a local variable that is not used and gets thrown away. So its a waste of space. Similarly you read the config file but throw away the results. Again a waste of space. And the same with readsets. Your init does a lot of work to no long term effect. @property def steps(self): return [ self.one, self.two, self.fmit, ] def one(self): a = 5 return a ... #@property def show(self): ftp=\n.join([str(idx + 1) + - + step.__name__ for idx, step in enumerate(self.steps)]) print ftp It is working In [5]: F = Foo() In [6]: F.show() 1- one 2- two 3- fmit Yes, as expected. Why if I define the data in the same way I have this error? ipython-input-83-a3c57022a089 in module() 1 rna.show() ipython-input-79-b1a3b6d221ae in show(self) 261 #@property 262 def show(self): -- 263 ftp=\n.join([str(idx + 1) + - + step.__name__ for idx, step in enumerate(self.steps)]) 264 265 print ftp AttributeError: 'str' object has no attribute '__name__' Because you didn't define it in the same way. Consider this example from the pastebin: @property def star(self): print Mitico Star return name Here you make star a property so when in steps you store self.star you are not storing a reference to the method, as you did above, you are storing the return value of star - name. Now in show() you try to take the __name__ of name but, as the error says, strings don't have __name__ attributes. The same applies to some, but not all, of the other method names in steps... You would make life much easier if you got rid of all the property stuff (some of it commented out and others not). Just use the methods and data attributes directly, it makes life so much easier. Here you find all the other code the principal are the same:http://pastebin.com/nYGEiXY4 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] Class errors
If the code I'm seeing is correct, the problem is the class is Jobs, and you instantiated a Job, which doesn't exit. Replace one with the other in either case should fix it. On Thu, Jan 22, 2015 at 11:11 AM, jarod...@libero.it jarod...@libero.it wrote: Dear All, I created a class that invoke from another file another class I get an error that I do not understand: gobal name Job is not defined However If I see the class imported I found the class Job. Any suggestion or example on class invoke another class #job,py class Jobs: . #trial.py from core.job import * class Second: def __initi__: tp = open(/tmp/file.txt) def gus(self): tr = Job() thanks so much!1 ___ 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] Class learning
#@property def show(self): ftp=\n.join([str(idx + 1) + - + step.__name__ for idx, step in enumerate(self.steps)]) Questions you should be asking yourself: What is self.steps? What type is it? In the case where this breaks with an error, what is self.steps then? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class learning
You are trying to use advanced features of Python, and they are not the right tool for what you're trying to do. Specifically, you're trying two things at the same time: 1. Properties, which allows method calls to look like simple variable access. 2. The __name__ special attribute on methods (reference: https://docs.python.org/2/reference/datamodel.html) to reflectively pick up a string that lets us get the name of a function. The problem is trying to use *both* of these features at the same time. It is self defeating. Here is a minimal example to demonstrate; ## class Test(object): @property def x(self): return 42 ## Consider the expression: Test2().x.__name__ This example is small enough that it should help to clarify what's going on. What did you want to happen? And what happens? Now look at: # class Test(object): def x(self): return 42 Test().x().__name__ # What do you expect to see when you run this, and why? The technical error in the first case is the same as the second. In short, I would strongly suggest you don't use @property, especially if you're learning the language. It's an advanced feature. In your particular case, you're getting into unnecessary trouble by using it. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class learning
On Fri, Jan 23, 2015 at 12:37 AM, jarod...@libero.it jarod...@libero.it wrote: Thanks for the help and patience! It is a function on the class so I suppose for read that function list I need self.steps Where I'm wrong? @property def steps(self): return [ self.trimmomatic, self.merge_trimmomatic_stats, self.star, self.picard_sort_sam, self.rnaseqc, self.wiggle, self.cufflinks, self.gq_seq_utils_exploratory_analysis_rnaseq ] Do each of these elements in this list support the operations you're performing on any single step? That is, the code that you have here: def show(self): ftp=\n.join([str(idx + 1) + - + step.__name__ for idx, step in enumerate(self.steps)]) seems to assume that every step must have a '__name__' property. But do all of the steps that you've put in there support '__name__'? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class errors
On Thu, Jan 22, 2015 at 8:11 AM, jarod...@libero.it jarod...@libero.it wrote: Dear All, I created a class that invoke from another file another class I get an error that I do not understand: gobal name Job is not defined Please use copy-and-paste. You just typed out the error message by hand: we can tell because the error message you're presenting is misspelled. Copy-and-paste it, as well as the surrounding text around it. However If I see the class imported I found the class Job. Ok. But where? In the code you present: #job,py class Jobs: . #trial.py from core.job import * class Second: def __initi__: tp = open(/tmp/file.txt) def gus(self): tr = Job() I don't see a class named 'Job'. I see a class named 'Jobs' defined in 'job.py', but that's a different class. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class errors
On 22Jan2015 17:11, jarod...@libero.it jarod...@libero.it wrote: I created a class that invoke from another file another class I get an error that I do not understand: gobal name Job is not defined However If I see the class imported I found the class Job. Any suggestion or example on class invoke another class First, please cut/paste error messages, filenames and code. Do not hand type them, as that introduces errors. #job,py For example, I suspect you mean job.py, not job,py. class Jobs: . #trial.py from core.job import * It is not recommended to import *. Just impor the names you need. It avoids _unexpected_ names leaking into your program: you might be using such a name for something else! class Second: def __initi__: tp = open(/tmp/file.txt) def gus(self): tr = Job() Because you have hand typed things I cannot be sure - it may just be a mistake - but job.py defines a class Jobs. In trial.py you use the name Job. Not the same! Cheers, Cameron Simpson c...@zip.com.au Beware of bugs in the above code; I have only proved it correct, not tried it. - Donald E. Knuth ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class to function
can you guys help explain. super thanks A class is like a blueprint. An instance of that class is like a house built from that blueprint. Think about it. An infinite number of houses could be constructed using those blueprints. But the architect only had to draw them once. __init__() is like the foundation of each house that is built. In otherwords, the stuff you do first when construction commences. Alan ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class to function
On 2014-05-25 09:20, R. Alan Monroe wrote: can you guys help explain. super thanks A class is like a blueprint. An instance of that class is like a house built from that blueprint. Think about it. An infinite number of houses could be constructed using those blueprints. But the architect only had to draw them once. __init__() is like the foundation of each house that is built. In otherwords, the stuff you do first when construction commences. Alan I very much like this analogy but might I suggest a slight modification? __init__() builds the house, and possibly provides minimum furnishings[1] (with parameters passed to init;) then your code (usually using the associated methods) flushes out the furnishings[1] (and makes use of them) as the needs of your program demand. [1] 'furnishings' in this analogy are DATA Does this fit? Comments welcome. Respectively submitted, ak ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class to function
On 25/05/14 16:39, rahmad akbar wrote: Hi guys i am trying to understand this code: http://nbviewer.ipython.org/gist/BenLangmead/6665861 i understand functions quite alright . but i have no idea about classes yet. Do you understand modules? Modules contain functions and data that you can reuse across programs. Are you comfortable with the idea of importing and using modules? Classes are one step on from modules. A module can contain data but that data is restricted in that you can only have a single instance of it. For example if you had a module full of functions for processing a data tree and the root was a module variable. You can load the tree and use it just fine. But if you want to work with more than one tree you either have to throw away (or cache) the old tree before populating the new one or combine both trees under a single root (which probably won't work well). To solve that you build the module functions and data into a Tree class. Then you can create multiple Trees each with their own root. To do that you take each of the module functions and put then into the class as methods. You then put the global root variable into the class as instance data. You do that by creating an __init__() method that accepts the root data as a parameter and populates the instance root variable (self.root). When you create an instance of a tree you pass in the root variable and Python magically calls the __init__() method, passing your root in to it. You probably have been doing this with things like strings for ages. You create a string by assigning a string literal s = 'my string' instead of explicitly calling s = str('my string') But the effect is the same. You create an instance of a string object which has methods attached, like upper(), split() etc, -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ 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] class to function
i am trying to understand this code: http://nbviewer.ipython.org/gist/BenLangmead/6665861 I'm slightly familiar with the purpose of the code. It's constructing a Suffix Tree, though not in linear time. Reading the code... ah. I see. This is enumerating through all suffixes, and building it by repeated insertion into a trie. http://en.wikipedia.org/wiki/Trie The classes are used here to represent structured data and operations to be performed on that structured data. The code fundamentally has a structured value called a Node, with two fields to represent the string label and the links to other nodes. Aside: there is a very good book by Dan Gusfield that talks about suffix trees and how to construct them called Algorithms on Strings, Trees and Sequences: Computer Science and Computational Biology http://www.amazon.com/Algorithms-Strings-Trees-Sequences-Computational/dp/0521585198 which you may want to look at if you're interested in these algorithms. It is probably not a good idea to try to intermix trying to understand an algorithm like this at the same time as you're learning basic features in your programming language. Consider a slightly simpler example to learn about classes, apart from the algorithms you are studying. Most good Python tutorials should cover how to use classes to build structured data and manipulate it. Alan Gauld's Python tutorial, for example, should have a section on this. http://www.alan-g.me.uk/tutor/tutclass.htm ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
Sangeeth Saravanaraj wrote: I am trying to capture an object initiation and deletion events using the __call__() and __del__() methods with the following approach. Note that there is no guarantee that __dell__ will ever be called. Usually it is better to introduce a weakref with callback. class A(object): def __init__(self, klass): print A::__init__() self._klass = klass def __call__(self): print A::__call__() return self._klass() def __del__(self): print A::__del__() class Parent1(object): def __init__(self): print Parent1:: __init__() super(Parent1, self).__init__() class Parent2(object): def __init__(self): print Parent2:: __init__() super(Parent2, self).__init__() @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B, self).__init__() def main(): b = B() if __name__ == __main__: main() I decorate a class, say class B (whose object initiation and deletion I wanted to capture) with a decorator class A. Please note that the class B is derived from two classes - Parent1 Parent2 and I want to use super() method to initialise the parent classes. When I executed the above code snippet, I ran into the following issue: A::__init__() A::__call__() B::__init__() Traceback (most recent call last): File so.py, line 40, in module main() File so.py, line 36, in main b = B() File so.py, line 10, in __call__ return self._klass() File so.py, line 32, in __init__ super(B, self).__init__() TypeError: must be type, not A A::__del__() When I commented super(B, self).__init__() in the class B :: __init__() method, it returned an object of type B and I was able to see the prints in the __call__ and __del__ methods but the __init__() methods of the base classes (Parent1 Parent2) are not called! From the error message, what I could understand is - the object returned by A::__call__() is not of type B but of type A. But when I put a print in the A::__call__() I could see it returns an object of type B and not A. Now the question is - With this approach to capture the initiation and deletion events of an object, how do I initialise the base classes using super()? You'd have to introduce a naming convention or rewrite your class to be aware of the wrapping in some way: @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B._klass, self).__init__() Not pretty. Or, is there any other better way to capture the __call__ and __del__ events for an object of a certain class - if so, how?! Most certainly, but you have to give some details about what you are up to first. PS: http://stackoverflow.com/questions/21826854/typeerror-when-using-super- method-with-class-decorator-for-a-derived-class ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
On Mon, Feb 24, 2014 at 10:53 PM, Peter Otten __pete...@web.de wrote: Sangeeth Saravanaraj wrote: I am trying to capture an object initiation and deletion events using the __call__() and __del__() methods with the following approach. Note that there is no guarantee that __dell__ will ever be called. Usually it is better to introduce a weakref with callback. class A(object): def __init__(self, klass): print A::__init__() self._klass = klass def __call__(self): print A::__call__() return self._klass() def __del__(self): print A::__del__() class Parent1(object): def __init__(self): print Parent1:: __init__() super(Parent1, self).__init__() class Parent2(object): def __init__(self): print Parent2:: __init__() super(Parent2, self).__init__() @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B, self).__init__() def main(): b = B() if __name__ == __main__: main() I decorate a class, say class B (whose object initiation and deletion I wanted to capture) with a decorator class A. Please note that the class B is derived from two classes - Parent1 Parent2 and I want to use super() method to initialise the parent classes. When I executed the above code snippet, I ran into the following issue: A::__init__() A::__call__() B::__init__() Traceback (most recent call last): File so.py, line 40, in module main() File so.py, line 36, in main b = B() File so.py, line 10, in __call__ return self._klass() File so.py, line 32, in __init__ super(B, self).__init__() TypeError: must be type, not A A::__del__() When I commented super(B, self).__init__() in the class B :: __init__() method, it returned an object of type B and I was able to see the prints in the __call__ and __del__ methods but the __init__() methods of the base classes (Parent1 Parent2) are not called! From the error message, what I could understand is - the object returned by A::__call__() is not of type B but of type A. But when I put a print in the A::__call__() I could see it returns an object of type B and not A. Now the question is - With this approach to capture the initiation and deletion events of an object, how do I initialise the base classes using super()? You'd have to introduce a naming convention or rewrite your class to be aware of the wrapping in some way: @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B._klass, self).__init__() Not pretty. Or, is there any other better way to capture the __call__ and __del__ events for an object of a certain class - if so, how?! Most certainly, but you have to give some details about what you are up to first. Sorry, I should have described what I was trying! I want to create a decorator which should do the following things: - When an object of the decorated class is created, the objects name (say the value of the incoming id argument) should be stored as a record in a table in a database. - When an object of the decorated class is deleted, the record with this deleted objects name (i.e. object.id) should be removed from the table. You can safely assume that all the database operations are working fine! Now, for example - consider the following snippet: @saveme class A(object): def __init__(self, id): self.id = id @saveme class B(object): def __init__(self, id): self.id = id saveme should do what I have explained earlier. a1 = A(A1) a2 = A(A2) a3 = A(A3) b1 = B(B1) b2 = B(B2) At this point if I query and print all the records in a table, I should get the following: output: [A1, A2, A3, B1, B2] del a1 del a2 del a3 del b1 del b2 At this point, all entries in the table should be deleted; query should return an empty list! And, I want to highlight that the classes that are being decorated with saveme can de derived classes too! What is the best way to do this?! Thank you, Sangeeth PS: http://stackoverflow.com/questions/21826854/typeerror-when-using-super- method-with-class-decorator-for-a-derived-class ___ 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] Class decorator on a derived class not initialising the base classes using super - TypeError
Sangeeth Saravanaraj wrote: On Mon, Feb 24, 2014 at 10:53 PM, Peter Otten __pete...@web.de wrote: Sangeeth Saravanaraj wrote: I am trying to capture an object initiation and deletion events using the __call__() and __del__() methods with the following approach. Note that there is no guarantee that __dell__ will ever be called. Usually it is better to introduce a weakref with callback. class A(object): def __init__(self, klass): print A::__init__() self._klass = klass def __call__(self): print A::__call__() return self._klass() def __del__(self): print A::__del__() class Parent1(object): def __init__(self): print Parent1:: __init__() super(Parent1, self).__init__() class Parent2(object): def __init__(self): print Parent2:: __init__() super(Parent2, self).__init__() @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B, self).__init__() def main(): b = B() if __name__ == __main__: main() I decorate a class, say class B (whose object initiation and deletion I wanted to capture) with a decorator class A. Please note that the class B is derived from two classes - Parent1 Parent2 and I want to use super() method to initialise the parent classes. When I executed the above code snippet, I ran into the following issue: A::__init__() A::__call__() B::__init__() Traceback (most recent call last): File so.py, line 40, in module main() File so.py, line 36, in main b = B() File so.py, line 10, in __call__ return self._klass() File so.py, line 32, in __init__ super(B, self).__init__() TypeError: must be type, not A A::__del__() When I commented super(B, self).__init__() in the class B :: __init__() method, it returned an object of type B and I was able to see the prints in the __call__ and __del__ methods but the __init__() methods of the base classes (Parent1 Parent2) are not called! From the error message, what I could understand is - the object returned by A::__call__() is not of type B but of type A. But when I put a print in the A::__call__() I could see it returns an object of type B and not A. Now the question is - With this approach to capture the initiation and deletion events of an object, how do I initialise the base classes using super()? You'd have to introduce a naming convention or rewrite your class to be aware of the wrapping in some way: @A class B(Parent1, Parent2): def __init__(self): print B::__init__() super(B._klass, self).__init__() Not pretty. Or, is there any other better way to capture the __call__ and __del__ events for an object of a certain class - if so, how?! Most certainly, but you have to give some details about what you are up to first. Sorry, I should have described what I was trying! I want to create a decorator which should do the following things: - When an object of the decorated class is created, the objects name (say the value of the incoming id argument) should be stored as a record in a table in a database. - When an object of the decorated class is deleted, the record with this deleted objects name (i.e. object.id) should be removed from the table. You can safely assume that all the database operations are working fine! Now, for example - consider the following snippet: @saveme class A(object): def __init__(self, id): self.id = id @saveme class B(object): def __init__(self, id): self.id = id saveme should do what I have explained earlier. a1 = A(A1) a2 = A(A2) a3 = A(A3) b1 = B(B1) b2 = B(B2) At this point if I query and print all the records in a table, I should get the following: output: [A1, A2, A3, B1, B2] del a1 del a2 del a3 del b1 del b2 At this point, all entries in the table should be deleted; query should return an empty list! And, I want to highlight that the classes that are being decorated with saveme can de derived classes too! What is the best way to do this?! I'm sorry, after a bit of try-and-error I could not come up with a good way to write such a decorator. My best effort so far uses inheritance: import itertools import weakref _registry = weakref.WeakValueDictionary() _next_id = lambda count=itertools.count(): next(count) def show(): print(list(_registry.values())) class Registered(object): def __init__(self, id=None): if id is None: id = _next_id() self.id = id _registry[id] = self def __repr__(self): return {}(id={!r}).format(self.__class__.__name__, self.id) class A(Registered): pass class B(Registered): pass class C(B): pass a1 = A() b1 = B() c1 = C() show() del a1 show() b2 = B() show() del b1 del c1
Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
On 02/24/2014 08:19 PM, Sangeeth Saravanaraj wrote: Sorry, I should have described what I was trying! I want to create a decorator which should do the following things: - When an object of the decorated class is created, the objects name (say the value of the incoming id argument) should be stored as a record in a table in a database. - When an object of the decorated class is deleted, the record with this deleted objects name (i.e. object.id) should be removed from the table. You can safely assume that all the database operations are working fine! Now, for example - consider the following snippet: @saveme class A(object): def __init__(self, id): self.id = id @saveme class B(object): def __init__(self, id): self.id = id saveme should do what I have explained earlier. a1 = A(A1) a2 = A(A2) a3 = A(A3) b1 = B(B1) b2 = B(B2) At this point if I query and print all the records in a table, I should get the following: output: [A1, A2, A3, B1, B2] del a1 del a2 del a3 del b1 del b2 At this point, all entries in the table should be deleted; query should return an empty list! And, I want to highlight that the classes that are being decorated with saveme can de derived classes too! What is the best way to do this?! Thank you, Sangeeth Your problem looks like a typical crosscutting (transversal) concern addressed by AOP (Aspect Oriented Programming). Their usual example is in fact logging. Look at the wikipedia page: https://en.wikipedia.org/wiki/Aspect-oriented_programming Not that it would help you solve it _in python_, but this may serve at least to better understand what kind of problem you are actually facing; and why it is annoying in programming (with common languages); what may be your options. [I have no better approach than yours, using magic metamethods, and a decorator to wrap it all.] d ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
Peter, Spir - thanks for your time and effort! I am posting this query to few more Python mailers. Thank you, Sangeeth On Tue, Feb 25, 2014 at 5:22 AM, spir denis.s...@gmail.com wrote: On 02/24/2014 08:19 PM, Sangeeth Saravanaraj wrote: Sorry, I should have described what I was trying! I want to create a decorator which should do the following things: - When an object of the decorated class is created, the objects name (say the value of the incoming id argument) should be stored as a record in a table in a database. - When an object of the decorated class is deleted, the record with this deleted objects name (i.e. object.id) should be removed from the table. You can safely assume that all the database operations are working fine! Now, for example - consider the following snippet: @saveme class A(object): def __init__(self, id): self.id = id @saveme class B(object): def __init__(self, id): self.id = id saveme should do what I have explained earlier. a1 = A(A1) a2 = A(A2) a3 = A(A3) b1 = B(B1) b2 = B(B2) At this point if I query and print all the records in a table, I should get the following: output: [A1, A2, A3, B1, B2] del a1 del a2 del a3 del b1 del b2 At this point, all entries in the table should be deleted; query should return an empty list! And, I want to highlight that the classes that are being decorated with saveme can de derived classes too! What is the best way to do this?! Thank you, Sangeeth Your problem looks like a typical crosscutting (transversal) concern addressed by AOP (Aspect Oriented Programming). Their usual example is in fact logging. Look at the wikipedia page: https://en.wikipedia.org/wiki/Aspect-oriented_programming Not that it would help you solve it _in python_, but this may serve at least to better understand what kind of problem you are actually facing; and why it is annoying in programming (with common languages); what may be your options. [I have no better approach than yours, using magic metamethods, and a decorator to wrap it all.] d ___ 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] class variables
On Sat, Dec 21, 2013 at 2:14 AM, Steven D'Aprano st...@pearwood.info wrote: (Sometimes, people will call them members, especially if they are used to C#. The meaning here is member as in an arm or leg, as in dismember, not member in the sense of belonging to a group.) A Python object isn't just a fixed-size block of data with members at fixed offsets. It stores its data dynamically in a dict. That said, CPython objects do have members as an implementation detail, including class-defined __slots__. The member_descriptor type is used to access members as attributes. For example, the read-only __base__ attribute of a class uses the following descriptor: vars(type)['__base__'] member '__base__' of 'type' objects Suppose we ask Python for polly.colour. Python looks at the instance polly, and checks to see if it has an instance attribute called polly. If it does, we're done. But if it doesn't, Python doesn't give up straight away, it next checks the class of polly, which is Parrot. Does Parrot have an attribute called polly? Yes it does, so that gets returned. It first has to check Parrot and its base classes (in Method Resolution Order, i.e. Parrot.__mro__) for a data descriptor (e.g. a property) named colour. An instance can't override a data descriptor. So unlike *getting* an attribute, which searches both the instance and the class, *setting* or *deleting* an attribute stops at the instance. Setting and deleting an attribute also has to start by searching the class and bases for data descriptors. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables [was Tutor Digest, Vol 118, Issue 99]
(I fixed the subject line for you.) On Sat, Dec 21, 2013 at 02:53:28AM -0500, Keith Winston wrote: On Sat, Dec 21, 2013 at 2:14 AM, tutor-requ...@python.org wrote: I don't like the terms class variable and instance variable. In the Python community, these are usually called class and instance attributes rather than variables or members. Hey Steven, that was a very generous explanation. Thanks! Very clear. I was floundering over the simple name/concept of attibute, and it had undermined my reading of other material. Your examples were extremely helpful. I think I understood everything you said (after a second reading). Glad to be of service! I keep hearing about how Python creates namespaces which I think are dictionaries, I'm going to have to look into that further to understand how some of this fits together. Think of a typical family. Unless you're one of George Foreman's five sons all called George, chances are that everyone in the family has a different name. (Or at least a different nickname.) Fred in your family is not the same as Fred in my family. In this case, the family plays the role of a namespace: everyone inside the family has a unique name that they are known by, but people in different families can have the same name. In general, a namespace is some sort of environment or container that holds identifiers (such as names, or ID numbers). Within a single namespace, all identifiers have to be unique, but two different namespaces can hold the same identifier. For example, in Python, each module is a namespace. If you have two files, say spam.py and eggs.py, the two modules may include variables with the same name: spam.thing = 23 eggs.thing = 42 Even though they are both called thing, they live in different namespaces so they can have different values. Python namespaces are usually dictionaries. The globals() function returns the global namespace, which is a dict. You will find all your global variables in it. Here's an example: py x = 23 py d = globals() py d['x'] 23 py d['x'] = 42 py x 42 (Note: operating directly on globals(), as I do in that example, is not a common thing to do. Python gives you the ability to do so, but it's quite rare to actually need it.) Classes and instances also behave as namespaces. Both normally have a special attribute called __dict__ (that's two underscores at the start and end of the name). Class.__dict__ holds the class attributes, including methods. The instance __dict__ holds the instance attributes. Rather than access the __dict__ directly, it is nearly always better to use getattr and setattr functions. That is: # don't do this obj.__dict__['attribute'] = 23 # this is better setattr(obj, 'attribute', 23) # but this is even better obj.attribute = 23 The main reason for using getattr and setattr is when you don't know the name of the attribute when you write the code, but only at runtime. For example: name = get_some_name() # returns some attribute name getattr(obj, name) You can't use obj.name, since that will return the attribute called literally name. In this case, you want the attribute named *by* name instead -- if name == colour, you want obj.colour, if name == height, you want obj.height, and so on. I think that's where Python is going when you're talking about looking up attributes (and it would include methods too, unless they're still functions... maybe they're methods for instances and functions for classes? Ok, I don't get that part yet). Methods and functions are another story, but in a nutshell, methods are just like functions except that they live inside classes, and when you call a method, it automatically gets the instance as the first argument. Confused? Here's an example, using a string method. Strings have a method, replace, that works like this: py the cat in the hat eats green ham.replace(cat, dog) 'the dog in the hat eats green ham' If replace were a function, we would write it something like this: # simplified version def replace(s, old, new): ... and you would call it like this: replace(the cat in the hat eats green ham, cat, dog) = returns the dog in the hat eats green ham So you can think of the difference between methods and functions that methods use the syntax: arg1.method(arg2, arg3, ...) instead of: function(arg1, arg2, arg3, ...) There are other differences, but that is the most important one. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables
On Sat, Dec 21, 2013 at 08:41:17AM -0500, eryksun wrote: On Sat, Dec 21, 2013 at 2:14 AM, Steven D'Aprano st...@pearwood.info wrote: (Sometimes, people will call them members, especially if they are used to C#. The meaning here is member as in an arm or leg, as in dismember, not member in the sense of belonging to a group.) A Python object isn't just a fixed-size block of data with members at fixed offsets. It stores its data dynamically in a dict. Yes, but that's just an implementation detail. There's no fundamental difference between attribute, member and (instance/class) variable. Different languages give them different names according to whatever vagaries the language creator considers important. C# happens to use fixed-sized records, Python happens to (usually) use dicts. Having said that, I do think it is useful to reserve the term member for the fixed-size block type, and attribute for the general term. At least when talking about Python. [...] For example, the read-only __base__ attribute of a class uses the following descriptor: vars(type)['__base__'] member '__base__' of 'type' objects Oooh, nice! I always forget about vars(), and end up messing about with __dict__. Suppose we ask Python for polly.colour. Python looks at the instance polly, and checks to see if it has an instance attribute called polly. [...] It first has to check Parrot and its base classes (in Method Resolution Order, i.e. Parrot.__mro__) for a data descriptor (e.g. a property) named colour. An instance can't override a data descriptor. I did say it was an over-simplified description. I didn't think it was helpful to start talking about descriptors to a beginner :-) For what it's worth, descriptors are both absolutely fundamental to how Python operates, and an advanced feature that newbies don't need to understand immediately, -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables
On Sat, Dec 21, 2013 at 12:40 PM, Steven D'Aprano st...@pearwood.info wrote: On Sat, Dec 21, 2013 at 08:41:17AM -0500, eryksun wrote: vars(type)['__base__'] member '__base__' of 'type' objects Oooh, nice! I always forget about vars(), and end up messing about with __dict__. It's a bit more efficient to use the __dict__ attribute, but I like built-in vars(). vars(obj) is basically doing the equivalent of getattr(obj, '__dict__'), so there's that plus the overhead of the call. vars has to play it safe. A class may define a custom __dict__ property, such as the tuple subclass created by namedtuple: from collections import namedtuple Point = namedtuple('Point', 'x y') p = Point(1, 2) type(vars(Point)['__dict__']) class 'property' vars(p) OrderedDict([('x', 1), ('y', 2)]) Even if an object has a dict, it would be wrong for vars to naively return a reference. A class might be overriding __getattribute__ to create dynamic attributes or raise an AttributeError for '__dict__'. Also, bypassing the descriptor would bypass the proxy protecting a class dict, enabling silliness: from ctypes import pythonapi, py_object # 3.3+ pythonapi.PyObject_GenericGetDict.restype = py_object pythonapi.PyObject_GenericGetDict.argtypes = [py_object] str_dict = pythonapi.PyObject_GenericGetDict(str) str_dict['lower'] = str_dict['upper'] 'abc'.lower() 'ABC' ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables
Hi, I am a little confused about class variables: I feel like I've repeatedly seen statements like this: please take a look at the archives - this topic has been discussed on this list recently. -nik -- * mirabilos is handling my post-1990 smartphone * mirabilos Aaah, it vibrates! Wherefore art thou, demonic device?? PGP-Fingerprint: 3C9D 54A4 7575 C026 FB17 FD26 B79A 3C16 A0C4 F296 signature.asc Description: Digital signature ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables
On 20/12/13 07:04, Keith Winston wrote: Class.pi == 3.14 # defined/set in the class def instance.pi == 3.14 # initially instance.pi = 4 # oops, changed it Class.pi == 3.14 # still Class.pi = rhubarb # oops, there I go again instance.pi == 4 # still Sorry if I'm beating this to a pulp, I think I've got it... You do have it. Think of it like an extension to any other form of name look up. The built in functions are available to you anywhere but you can override them in your code. Python looks first to see if you have defined your own version, if you don't it looks in the built in names. Similarly if you have a name defined within the instance it will use that if not it will look in the class. My personal rule for this is if you want the class variable always access it via the class rather than the instance. But that falls down when processing a polymorphic collection where some instances may have instance variables and others only class variables. So a loop like this for obj in myMixedObjectList: obj.someName = 42 Those instances that didn't have an instance var called someName before, have one now. That may not be a good thing, especially if the objects methods use self.someName to access the class variable. But these cases are relatively rare in my experience. Lists of objects are usually more closely related than in the example above. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ 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] class variables
On Fri, Dec 20, 2013 at 5:20 AM, Alan Gauld alan.ga...@btinternet.com wrote: Similarly if you have a name defined within the instance it will use that if not it will look in the class. An instance can generally shadow class attributes, except properties and other data descriptors defined by the class are given precedence when looking up attributes: instance = Class() Class.pi = property(lambda s: 3.14) instance.pi 3.14 instance.pi = 4 Traceback (most recent call last): File stdin, line 1, in module AttributeError: can't set attribute The property is used even if you manually assign pi in the instance dict: vars(instance)['pi'] = 4 vars(instance) {'pi': 4} instance.pi 3.14 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class variables
On Fri, Dec 20, 2013 at 02:04:49AM -0500, Keith Winston wrote: I am a little confused about class variables: I feel like I've repeatedly seen statements like this: I don't like the terms class variable and instance variable. In the Python community, these are usually called class and instance attributes rather than variables or members. (Sometimes, people will call them members, especially if they are used to C#. The meaning here is member as in an arm or leg, as in dismember, not member in the sense of belonging to a group.) Normally, we say that a string variable is a variable holding a string, a float variable is a variable holding a float, an integer variable is a variable holding an integer. So a class variable ought to be a variable holding a class, and an instance variable ought to be a variable holding an instance. In Python we can have both of those things! Unlike Java, classes are first-class citizens and can be treated exactly the same as strings, floats, ints and other values. So a class variable would be something like this: for C in list_of_classes: # Here, C holds a class, and so we might call # it a class variable, not a string variable do_something_with(variable) There is only one copy of the class variable and when any one object makes a change to a class variable, that change will be seen by all the other instances. Object variables are owned by each individual object/instance of the class. In this case, each object has its own copy Talking about copies is not a good way to understand this. It might make sense to talk about copies in some other languages, but not in Python. (Or any of many languages with similar behaviour, like Ruby or Java.) I'm going to give you a simple example demonstrating why thinking about copies is completely the wrong thing to do here. If you already understand why copies is wrong, you can skip ahead here, but otherwise you need to understand this even though it doesn't directly answer your question. Given a simple class, we can set an attribute on a couple of instances and see what happens. Copy and paste these lines into a Python interactive session, and see if you can guess what output the print will give: class Test: pass spam = Test() eggs = Test() obj = [] spam.attribute = obj eggs.attribute = obj spam.attribute.append(Surprise!) print(eggs.attribute) If you think about *copies*, you might think that spam and eggs have their own independent copies of the empty list. But that's not what Python does. You don't have two copies of the list, you have a single list, and two independent references to it. (Actually, there are three: obj, spam.attribute, eggs.attribute.) But only one list, with three different names. This is similar to people. For instance, the President of the USA is known as Mr President to his staff, POTUS to the military, Barrack to his wife Michelle, Mr Obama to historians and journalists, Dad to his children, and so forth. But they all refer to the same person. In a few years, Barrack Obama will stand down as president, and somebody else will be known as Mr President and POTUS, but he'll still be Barrack to Michelle. Python treats objects exactly the same. You can have lots of names for the same object. Some objects, like lists, can be modified in place. Other objects, like strings and ints, cannot be. In Python, we refer to this system as name binding. You have things which are names, like obj, and we associate an object to that name. Another term for this is a reference, in the generic sense that we refer to things. So we can bind an object to a name: obj = [] We can *unbind* the name as well: del obj In Python, assignment with = is name binding, and not copying: spam.attribute = obj does not make a copy of the list, it just makes spam.attribute and obj two different names for the same list. And likewise for eggs.attribute. Hopefully now you can understand why it is wrong to talk about copies here. In Python, you only get copies when you explicitly call a function which makes a copy, and never from = assignment (name binding). Now let me get back to your original question: But when I test, I see some interesting things: first (and this is consistent with above) the class variables are created when the class is defined, and can be used even without any instances of the class being created. Correct. Not only that, but class attributes will show up from instances as well: py class Parrot: ... colour = green ... def description(self): ... return You see a %s coloured bird. % self.colour ... py polly = Parrot() py polly.description() 'You see a green coloured bird.' Second, initially confusing but maybe I understand... there are pointers to the class variables associated with every instance of the object, Don't think about pointers. That's too specific. It just so happens that the version of Python you are using
Re: [Tutor] Class attribute error
Hi, Thanks for correcting me. The solutions mentioned by Dominik and Alan have simplified the concept to me now. Regards, Reuben On Sun, Nov 17, 2013 at 5:25 AM, Dominik George n...@naturalnet.de wrote: On Sat, Nov 16, 2013 at 09:13:13AM -0800, reutest wrote: class myclass(): def test(self): print print this line if __name__ == '__main__': myclass.run() Is that a question? If I were to guess, I'd say you should have asked Why does this say that myclass does not havea run method?. Then the simple answer is: Because, well, it doesn't! Why do you expect it to have one? -nik -- Wer den Grünkohl nicht ehrt, ist der Mettwurst nicht wert! PGP-Fingerprint: 3C9D 54A4 7575 C026 FB17 FD26 B79A 3C16 A0C4 F296 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class attribute error
On Sat, Nov 16, 2013 at 09:13:13AM -0800, reutest wrote: class myclass(): def test(self): print print this line if __name__ == '__main__': myclass.run() Is that a question? If I were to guess, I'd say you should have asked Why does this say that myclass does not havea run method?. Then the simple answer is: Because, well, it doesn't! Why do you expect it to have one? -nik -- Wer den Grünkohl nicht ehrt, ist der Mettwurst nicht wert! PGP-Fingerprint: 3C9D 54A4 7575 C026 FB17 FD26 B79A 3C16 A0C4 F296 signature.asc Description: Digital signature ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class attribute error
On 16/11/13 17:13, reutest wrote: class myclass(): def test(self): print print this line if __name__ == '__main__': myclass.run() If you have a question it helps if you ask it rather than have us guess. In this case I'm guessing you got an error and you are wondering why? It's because you are calling the run() class method of myclass. And there is no such method. If that's not your question please post again with a bit more of a clue about what you want to know. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ 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] class decorator question
On 06/10/2013 03:58, Steven D'Aprano wrote: On Sun, Oct 06, 2013 at 01:06:18AM +0100, Alan Gauld wrote: On 05/10/13 20:26, Albert-Jan Roskam wrote: General question: I am using pastebin now. Is that okay, For code as short as this it's probably best kept with the message. But once you get to 100+ lines its more debatable and if you get to 200+ lines I'd definitely say a pastebin is better. If somebody is tempted to post 200+ lines here, they probably shouldn't. Instead, they should read this: http://sscce.org/ I totally agree. -- Roses are red, Violets are blue, Most poems rhyme, But this one doesn't. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class decorator question
- Original Message - From: Steven D'Aprano st...@pearwood.info To: tutor@python.org Cc: Sent: Sunday, October 6, 2013 4:52 AM Subject: Re: [Tutor] class decorator question On Sat, Oct 05, 2013 at 12:26:14PM -0700, Albert-Jan Roskam wrote: On http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/ I saw a very cool and useful example of a class decorator. It (re)implements __str__ and __unicode__ in case Python 2 is used. For Python 3, the decorator does nothing. I wanted to generalize this decorator so the __str__ method under Python 2 encodes the string to an arbitrary encoding. This is what I've created: http://pastebin.com/vghD1bVJ. It works, but the code is not very easy to understand, I am affraid. It's easy to understand, it's just doing it the wrong way. It creates and subclass of your class, which it shouldn't do. Why not? Because it's an unusual coding pattern? Or is it ineffecient? It is both of those things. (Well, the inefficiency is minor.) My main objection is that it is inelegant, like using a screwdriver as a chisel instead of using a chisel -- even when it's good enough, it's not something you want other people to see you doing if you care about looking like a craftsman :-) or use a shoe to hammer a nail in the wall... ;-) Another issue is to do with naming. In your example, you decorate Test. What that means in practice is that you create a new class, Klass(Test), throw away Test, and bind Klass to the top-level name Test. So in effect you're doing this: class Test # The undecorated version. class Klass(Test) # Subclass it inside the decorator. Test = Klass # throw away the original and re-use the variable name. But classes, like functions, have *two* names. They have the name they are bound to, the variable name (*usually* one of these, but sometimes zero or two or more). And they have their own internal name: Test.__name__ = returns Klass This will make debugging unneccesarily confusing. If you use your decorator three times: @implements_to_string class Spam @implements_to_string class Eggs @implements_to_string class Cheese instances of all three of Spam, Eggs and Cheese will claim to be instances of Klass. That would indeed be *very* confusing. Now there is a simple work-around for this: inside the decorator, call Klass.__name__ = cls.__name__ before returning. But that leads to another issue, where instances of the parent, undecorated, class (if any!) and instances of the child, decorated, class both claim to be from the same Test class. This is more of theoretical concern, since you're unlikely to be instantiating the undecorated parent class. I subclassed because I needed the encoding value in the decorator. But subclassing may indeed have been overkill. Yes :-) The encoding value isn't actually defined until long after the decorator has finished doing its work, after the class is decorated, and an instance is defined. So there is no encoding value used in the decorator itself. The decorator can trivially refer to the encoding value, so long as that doesn't actually get executed until after an instance is created: def decorate(cls): def spam(self): print(self.encoding) cls.spam = spam return cls works fine without subclassing. waah, why didn't I think of this? I've been making this way more complicated than needed. self.__dict__[encoding] = self.encoding (see also below) was another way I considered to pass the encoding value from the class to its decorator. I even considered making a class decorator with arguments. All unnecesary. Here's a better approach: inject the appropriate methods into the class directly. Here's a version for Python 3: [...] This avoids overwriting __str__ if it is already defined, and likewise for __bytes__. Doesn't a class always have __str__ implementation? No. Where is the __str__ implementation here? class X: pass This class defines no methods at all. Its *superclass*, object in Python 3, defines methods such as __str__. But you'll notice that I didn't call hasattr(cls, '__str__') since that will return True, due to object having a __str__ method. I called '__str__' in cls.__dict__ which only returns True if cls explicitly defines a __str__ method. aahh, yes, of course these are not the same so 'method_name' in cls.__dict__ tests whether method_name is *implemented* in that class. In many/most cases hasattr is all you need because you want to know whether method_name can be *called* in that class. Nice, thanks Steven. I made a couple of versions after reading your advise. The main change that I still had to somehow retrieve the encoding value from the class to be decorated (decoratee?). I simply stored it in __dict__. Here is the second
Re: [Tutor] class decorator question
___ From: Steven D'Aprano st...@pearwood.info To: tutor@python.org Sent: Saturday, October 5, 2013 3:14 PM Subject: Re: [Tutor] class decorator question On Sat, Oct 05, 2013 at 05:33:46AM -0700, Albert-Jan Roskam wrote: Hi, On http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/ I saw a very cool and useful example of a class decorator. It (re)implements __str__ and __unicode__ in case Python 2 is used. For Python 3, the decorator does nothing. I wanted to generalize this decorator so the __str__ method under Python 2 encodes the string to an arbitrary encoding. This is what I've created: http://pastebin.com/vghD1bVJ. It works, but the code is not very easy to understand, I am affraid. It's easy to understand, it's just doing it the wrong way. It creates and subclass of your class, which it shouldn't do. Why not? Because it's an unusual coding pattern? Or is it ineffecient? I subclassed because I needed the encoding value in the decorator. But subclassing may indeed have been overkill. Here's a better approach: inject the appropriate methods into the class directly. Here's a version for Python 3: def decorate(cls): if '__str__' not in cls.__dict__: # inject __str__ method def __str__(self): ... cls.__str__ = __str__ if '__bytes__' not in cls.__dict__: # like above return cls This avoids overwriting __str__ if it is already defined, and likewise for __bytes__. Doesn't a class always have __str__ implementation? class Foo(object): pass f = Foo() f.__str__ method-wrapper '__str__' of Foo object at 0xb583642c Foo.__str__ slot wrapper '__str__' of 'object' objects Or is it? And I have no idea how to call the class Klass. Maybe reimplements_Test? Is this a good approach, or can this be done in an easier way? I would *really* like keep statements if sys.version_info[0] == 3... separate from the main code. Also, learning about class decorators is cool ;-). So the code below... mehhh no sir, I don't like it. Btw, that was a quote: http://www.youtube.com/watch?v=dQ3acvz5LfI ;-) def __str__(self): if sys.version_info[0] == 3: blah else: bleh if sys.version_info[0] == 2: def __unicode__(self): blh That performs the version check every time the __str__ method is called. Good point. Better would be something like this: if sys.version_info[0] == 2: def __str__(self): ... def __unicode__(self): ... else: def __bytes__(self): ... def __str__(self): ... If you don't like repeating the code twice, once for version 2 and once for version 3, you may be able to define the methods once, then rename them, something like this: # Assume version 3 def __str__(self): ... def __bytes__(self): ... if sys.version_info[0] == 2: __str__.__name__ = '__unicode__' __bytes.__name__ = '__str__' # Inject into the class, as above. cls.__unicode__ = __str__ cls.__str__ = __bytes__ else: cls.__str__ = __str__ cls.__bytes__ = __bytes__ Combining this with the decorator is left for you :-) Nice, thanks Steven. I made a couple of versions after reading your advise. The main change that I still had to somehow retrieve the encoding value from the class to be decorated (decoratee?). I simply stored it in __dict__. Here is the second version that I created: http://pastebin.com/te3Ap50C. I tested it in Python 2 and 3. The Test class contains __str__ and __unicode__ which are renamed and redefined by the decorator if Python 3 (or 4, or..) is used. General question: I am using pastebin now. Is that okay, given that this is not part of the memory of the Python Tutor archive? It might be annoying if people search the archives and get 404s if they try to follow these links. Just in case I am also pasting the code below: from __future__ import print_function import sys def decorate(cls): print(decorate called) if sys.version_info[0] 2: cls.__dict__[__str__].__name__ = '__bytes__' cls.__dict__[__unicode__].__name__ = '__str__' cls.__bytes__ = cls.__dict__[__str__] cls.__str__ = cls.__dict__[__unicode__] return cls @decorate class Test(object): def __init__(self): self.__dict__[encoding] = self.encoding def __str__(self): return str called.encode(self.encoding) def __unicode__(self): return unicode called @property def encoding(self): In reality this method extracts the encoding from a file return utf-8 # rot13 no longer exists in Python3 if __name__ == __main__: t = Test() if sys.version_info[0] == 2: print(unicode(t)) print(str(t)) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo
Re: [Tutor] class decorator question
On 05/10/13 20:26, Albert-Jan Roskam wrote: General question: I am using pastebin now. Is that okay, For code as short as this it's probably best kept with the message. But once you get to 100+ lines its more debatable and if you get to 200+ lines I'd definitely say a pastebin is better. from __future__ import print_function import sys def decorate(cls): print(decorate called) if sys.version_info[0] 2: cls.__dict__[__str__].__name__ = '__bytes__' cls.__dict__[__unicode__].__name__ = '__str__' cls.__bytes__ = cls.__dict__[__str__] cls.__str__ = cls.__dict__[__unicode__] return cls @decorate class Test(object): def __init__(self): self.__dict__[encoding] = self.encoding def __str__(self): return str called.encode(self.encoding) def __unicode__(self): return unicode called @property def encoding(self): In reality this method extracts the encoding from a file return utf-8 # rot13 no longer exists in Python3 if __name__ == __main__: t = Test() if sys.version_info[0] == 2: print(unicode(t)) print(str(t)) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ 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] class decorator question
On Sat, Oct 05, 2013 at 12:26:14PM -0700, Albert-Jan Roskam wrote: On http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/ I saw a very cool and useful example of a class decorator. It (re)implements __str__ and __unicode__ in case Python 2 is used. For Python 3, the decorator does nothing. I wanted to generalize this decorator so the __str__ method under Python 2 encodes the string to an arbitrary encoding. This is what I've created: http://pastebin.com/vghD1bVJ. It works, but the code is not very easy to understand, I am affraid. It's easy to understand, it's just doing it the wrong way. It creates and subclass of your class, which it shouldn't do. Why not? Because it's an unusual coding pattern? Or is it ineffecient? It is both of those things. (Well, the inefficiency is minor.) My main objection is that it is inelegant, like using a screwdriver as a chisel instead of using a chisel -- even when it's good enough, it's not something you want other people to see you doing if you care about looking like a craftsman :-) Another issue is to do with naming. In your example, you decorate Test. What that means in practice is that you create a new class, Klass(Test), throw away Test, and bind Klass to the top-level name Test. So in effect you're doing this: class Test # The undecorated version. class Klass(Test) # Subclass it inside the decorator. Test = Klass # throw away the original and re-use the variable name. But classes, like functions, have *two* names. They have the name they are bound to, the variable name (*usually* one of these, but sometimes zero or two or more). And they have their own internal name: Test.__name__ = returns Klass This will make debugging unneccesarily confusing. If you use your decorator three times: @implements_to_string class Spam @implements_to_string class Eggs @implements_to_string class Cheese instances of all three of Spam, Eggs and Cheese will claim to be instances of Klass. Now there is a simple work-around for this: inside the decorator, call Klass.__name__ = cls.__name__ before returning. But that leads to another issue, where instances of the parent, undecorated, class (if any!) and instances of the child, decorated, class both claim to be from the same Test class. This is more of theoretical concern, since you're unlikely to be instantiating the undecorated parent class. I subclassed because I needed the encoding value in the decorator. But subclassing may indeed have been overkill. Yes :-) The encoding value isn't actually defined until long after the decorator has finished doing its work, after the class is decorated, and an instance is defined. So there is no encoding value used in the decorator itself. The decorator can trivially refer to the encoding value, so long as that doesn't actually get executed until after an instance is created: def decorate(cls): def spam(self): print(self.encoding) cls.spam = spam return cls works fine without subclassing. Here's a better approach: inject the appropriate methods into the class directly. Here's a version for Python 3: [...] This avoids overwriting __str__ if it is already defined, and likewise for __bytes__. Doesn't a class always have __str__ implementation? No. Where is the __str__ implementation here? class X: pass This class defines no methods at all. Its *superclass*, object in Python 3, defines methods such as __str__. But you'll notice that I didn't call hasattr(cls, '__str__') since that will return True, due to object having a __str__ method. I called '__str__' in cls.__dict__ which only returns True if cls explicitly defines a __str__ method. Nice, thanks Steven. I made a couple of versions after reading your advise. The main change that I still had to somehow retrieve the encoding value from the class to be decorated (decoratee?). I simply stored it in __dict__. Here is the second version that I created: http://pastebin.com/te3Ap50C. I tested it in Python 2 and 3. Not sufficiently :-) Your test class has problems. See below. The Test class contains __str__ and __unicode__ which are renamed and redefined by the decorator if Python 3 (or 4, or..) is used. General question: I am using pastebin now. Is that okay, given that this is not part of the memory of the Python Tutor archive? It might be annoying if people search the archives and get 404s if they try to follow these links. Just in case I am also pasting the code below: In my opinion, no it's not okay, particularly if your code is short enough to be posted here. Just because a pserson has access to this mailing list doesn't necessarily mean they have access to pastebin. It might be blocked. The site might be down. They might object to websites that require Javascript (pastebin doesn't *require* it, but it's only a matter of time...). Or they may simply be too busy/lazy to
Re: [Tutor] class decorator question
On Sun, Oct 06, 2013 at 01:06:18AM +0100, Alan Gauld wrote: On 05/10/13 20:26, Albert-Jan Roskam wrote: General question: I am using pastebin now. Is that okay, For code as short as this it's probably best kept with the message. But once you get to 100+ lines its more debatable and if you get to 200+ lines I'd definitely say a pastebin is better. If somebody is tempted to post 200+ lines here, they probably shouldn't. Instead, they should read this: http://sscce.org/ -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class data member and objects of class in python
i am learning how a __class__ data member behaves in python as compared to static data member in java [...] The error is not related to class variables. Also could you elaborate on what you intended to find out with this snippet? class PizzaShop(): pizza_stock = 10 def get_pizza(self): while not PizzaShop.pizza_stock: PizzaShop.pizza_stock -= 1 yield take yours pizza order, total pizzas left {}.format(PizzaShop.pizza_stock) The condition in the while loop is wrong. bool(PizzaShop.pizza_stock) is True for all values but 0. (All numbers but 0 are considered True.) The while loop does its commands while the condition holds True. When you do not PizzaShop.pizza_stock it will return False for values other than 0, therefor the loop is never run and on exit of get_pizza it raises StopIteration to indicate that there are no more values to be yielded. mypizza_shop = PizzaShop() pizza_order = mypizza_shop.get_pizza() # iterator is obtained print a pizza pls!! {}:.format(pizza_order.next()) print a pizza pls!! {}:.format(pizza_order.next()) You might want to catch StopIteration here so that you can handle the case that the shop runs out of the initial stack of pizzas. ;) -- Felix Dietrich ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class data member and objects of class in python
class PizzaShop(): pizza_stock = 10 def get_pizza(self): while PizzaShop.pizza_stock: PizzaShop.pizza_stock -= 1 yield take yours pizza order, total pizzas left {}.format(PizzaShop.pizza_stock) mypizza_shop = PizzaShop() pizza_order = mypizza_shop.get_pizza() # print {}.format(repr(pizza_order.next())) for order in pizza_order: print {}.format(repr(order)) domino_pizza_store = mypizza_shop.get_pizza() print {}.format(repr(domino_pizza_store.next())) mypizza_shop.pizza_stock = 10 domino_pizza_store = mypizza_shop.get_pizza() print {}.format(repr(domino_pizza_store.next())) can't we again use the same object mypizza_shop once its generator is exhausted On Thu, Sep 12, 2013 at 6:53 AM, Marc Tompkins marc.tompk...@gmail.comwrote: On Wed, Sep 11, 2013 at 5:40 AM, zubair alam zubair.alam@gmail.comwrote: i am learning how a __class__ data member behaves in python as compared to static data member in java, but following code is throwing error class PizzaShop(): pizza_stock = 10 def get_pizza(self): while not PizzaShop.pizza_stock: PizzaShop.pizza_stock -= 1 yield take yours pizza order, total pizzas left {}.format(PizzaShop.pizza_stock) mypizza_shop = PizzaShop() pizza_order = mypizza_shop.get_pizza() # iterator is obtained print a pizza pls!! {}:.format(pizza_order.next()) print a pizza pls!! {}:.format(pizza_order.next()) output: Traceback (most recent call last): File /home/scott/pythonfiles/core_python/pizza.py, line 10, in module print a pizza pls!! {}:.format(pizza_order.next()) StopIteration don't know where i am doing mistakeany help will be appreciated... i have other questions on based on this class Change while not PizzaShop.pizza_stock: to while PizzaShop.pizza_stock:; I get the following output: a pizza pls!! take yours pizza order, total pizzas left 9: a pizza pls!! take yours pizza order, total pizzas left 8: ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class data member and objects of class in python
On 12/09/13 10:10, zubair alam wrote: class PizzaShop(): pizza_stock = 10 def get_pizza(self): while PizzaShop.pizza_stock: PizzaShop.pizza_stock -= 1 yield take yours pizza order, total pizzas left {}.format(PizzaShop.pizza_stock) mypizza_shop = PizzaShop() pizza_order = mypizza_shop.get_pizza() for order in pizza_order: print {}.format(repr(order)) You might as well just use print order domino_pizza_store = mypizza_shop.get_pizza() print {}.format(repr(domino_pizza_store.next())) mypizza_shop.pizza_stock = 10 This preobably isn't doing what you think it is. This is creating a new instance attribute in the mypizza_shop instance it is not resetting the class attribute. For that you would need to use PizzaShop.pizza_stock = 10 can't we again use the same object mypizza_shop once its generator is exhausted You can't use the same iterator again but you can get a new one. But your problem here is that you have not reset the class stock level. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ 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] class data member and objects of class in python
On 12/9/2013 05:10, zubair alam wrote: div dir=ltrdivclass PizzaShop():/divdiv pizza_stock = 10/divdiv def get_pizza(self):/divdiv while PizzaShop.pizza_stock:/divdiv PizzaShop.pizza_stock -= 1/divdiv yield quot;take yours pizza order, total pizzas left {}quot;.format(PizzaShop.pizza_stock)/div divbr/divdivmypizza_shop = PizzaShop()/divdivpizza_order = mypizza_shop.get_pizza() /divdiv# print quot;{}quot;.format(repr(pizza_order.next()))/divdivbr/divdivfor order in pizza_order:/divdiv span class= style=white-space:pre /spanprint quot;{}quot;.format(repr(order))/divdivbr/divdivdomino_pizza_store = mypizza_shop.get_pizza()/divdivprint quot;{}quot;.format(repr(domino_pizza_store.next()))/div divbr/divdivmypizza_shop.pizza_stock = 10/divdivbr/divdivdomino_pizza_store = mypizza_shop.get_pizza()/divdivprint quot;{}quot;.format(repr(domino_pizza_store.next()))/divdivbr/divdivbr /divdivcan#39;t we again use the same object mypizza_shop once its generator is exhausted/div/divdiv class=gmail_extrabrbrdiv class=gmail_quoteOn Thu, Sep 12, 2013 at 6:53 AM, Marc Tompkins span dir=ltrlt;a href=mailto:marc.tompk...@gmail.com; target=_blankmarc.tompk...@gmail.com/agt;/span wrote:br Please use text email, not hmtl. The indentation of your program was messed up in places, and I can't tell whether it was you or the email program that messed it up. This is a text newgroup, and html doesn't work reliably. As Alan has said, you're confusing class attributes with instance attributes. But I wonder if the mistake is actually the reverse of what he says. Do you intend that an instance of PizzaShop refers to a particul pizza shop, and that it has its own inventory, independent of all other pizza shop instances? in that case all use of the class attribute pizza_stock = 10 is bogus. To re-iterate the other point Alan made, an iterator is *required* to continue to throw Stopiteration once its exhausted and has thrown it once, even if new items show up that it could have used. But you can readily make a new iterator from the same mypizza_shop, once you set its pizza_stock to a nonzero value. -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class data member and objects of class in python
On Wed, Sep 11, 2013 at 5:40 AM, zubair alam zubair.alam@gmail.comwrote: i am learning how a __class__ data member behaves in python as compared to static data member in java, but following code is throwing error class PizzaShop(): pizza_stock = 10 def get_pizza(self): while not PizzaShop.pizza_stock: PizzaShop.pizza_stock -= 1 yield take yours pizza order, total pizzas left {}.format(PizzaShop.pizza_stock) mypizza_shop = PizzaShop() pizza_order = mypizza_shop.get_pizza() # iterator is obtained print a pizza pls!! {}:.format(pizza_order.next()) print a pizza pls!! {}:.format(pizza_order.next()) output: Traceback (most recent call last): File /home/scott/pythonfiles/core_python/pizza.py, line 10, in module print a pizza pls!! {}:.format(pizza_order.next()) StopIteration don't know where i am doing mistakeany help will be appreciated... i have other questions on based on this class Change while not PizzaShop.pizza_stock: to while PizzaShop.pizza_stock:; I get the following output: a pizza pls!! take yours pizza order, total pizzas left 9: a pizza pls!! take yours pizza order, total pizzas left 8: ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class-based generator
On 18 February 2013 07:36, Michael O'Leary mich...@seomoz.org wrote: I wrote some code to create tasks to be run in a queue based system last week. It consisted of a big monolithic function that consisted of two parts: 1) read data from a file and create dictionaries and lists to iterate through 2) iterate through the lists creating a job data file and a task for the queue one at a time until all of the data is dealt with My boss reviewed my code and said that it would be more reusable and Pythonic if I refactored it as a generator that created job data files and iterated by calling the generator and putting a task on the queue for each job data file that was obtained. This made sense to me, and since the code does a bunch of conversion of the data in the input file(s) to make it easier and faster to iterate through the data, I decided to create a class for the generator and put that conversion code into its __init__ function. So the class looked like this: It's not a generator if you create a class for it. Your class is (trying to be) an iterator. class JobFileGenerator: def __init__(self, filedata, output_file_prefix, job_size): convert filedata to a more usable form def next(self): while there is more data: yield a job data file next() should return a single item not a generator that yields items. If you perhaps rename the next function as __iter__ then it will be a proper iterator. I suspect however that your boss just wants you to write a single generator function rather than an iterator class. For example: def generate_jobs(): prepare while data: yield job for job in generate_jobs(): queue job ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class-based generator
Michael O'Leary wrote: I wrote some code to create tasks to be run in a queue based system last week. It consisted of a big monolithic function that consisted of two parts: 1) read data from a file and create dictionaries and lists to iterate through 2) iterate through the lists creating a job data file and a task for the queue one at a time until all of the data is dealt with My boss reviewed my code and said that it would be more reusable and Pythonic if I refactored it as a generator that created job data files and iterated by calling the generator and putting a task on the queue for each job data file that was obtained. This made sense to me, and since the code does a bunch of conversion of the data in the input file(s) to make it easier and faster to iterate through the data, I decided to create a class for the generator and put that conversion code into its __init__ function. So the class looked like this: class JobFileGenerator: def __init__(self, filedata, output_file_prefix, job_size): convert filedata to a more usable form def next(self): while there is more data: yield a job data file The problem is that the generator object is not created until you call next(), so the calling code has to look like this: gen = JobFileGenerator(data, output_, 20).next() for datafile in gen.next(): put a job that uses datafile into the queue This code works OK, but I don't like that it needs to call next() once to get a generator and then call next() again repeatedly to get the data for the jobs. If I were to write this without a class as a single generator function, it would not have to do this, but it would have the monolithic structure that my boss objected to. Would it work to do this: for datafile in JobFileGenerator(data, output_, 20).next(): put a job that uses datafile into the queue or would that cause the JobFileGenerator's __init__ function to be called more than once? Are there examples I could look at of generator functions defined on classes similar to this, or is it considered a bad idea to mix the two paradigms? Thanks, Mike You are abusing the next method; it is called once to build a generator. The convention for that is to use either a descriptive name (jobs() or somesuch) or __iter__(): class JobFile: def __init__(self, filedata, output_file_prefix, job_size): convert filedata to a more usable form def __iter__(self): while there is more data: yield a job data file for job in JobFile(data, output_, 20): put a job that uses datafile into the queue Here the generator is created by the implicit call to JobFile.__iter__() at the start of the for loop. Subsequent iterations call next() on the generator returned by that call. If you want the class itself to generate items you need a different approach: class JobFileIter: def __init__(self, filedata, output_file_prefix, job_size): convert filedata to a more usable form self._done = False def __iter__(self): return self def next(self): if self._done or no more data: self._done = True raise StopIteration return a job data file for job in JobFileIter(data, output_, 20): put a job that uses datafile into the queue Here __iter__() returns the JobFileIter instance, so for every iteration of the for loop JobFileIter.next() will be called -- until a StopIteration is raised. That said, it is often sufficient to refactor complex code into a few dedicated functions -- Python is not Java, after all. PS I'm assuming Python 2 -- for Python 3 the next() method must be replaced by __next__(). ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] 'class' for someone with no object oriented programming experience
From: Tutor [mailto:tutor-bounces+terrence.brannon=bankofamerica@python.org] On Behalf Of Art Scheel Sent: Tuesday, September 11, 2012 3:34 PM To: tutor@python.org Subject: [Tutor] 'class' for someone with no object oriented programming experience Are there any better resources for learning classes for someone who's never touched object oriented programming in the past besides basic interpretation for debugging purposes? [Terrence Brannon] Why don't you read this http://docs.python.org/tutorial/classes.html and write to this list regarding the first thing you don't understand. -- This message w/attachments (message) is intended solely for the use of the intended recipient(s) and may contain information that is privileged, confidential or proprietary. If you are not an intended recipient, please notify the sender, and then please delete and destroy all copies and attachments, and be advised that any review or dissemination of, or the taking of any action in reliance on, the information contained in or attached to this message is prohibited. Unless specifically indicated, this message is not an offer to sell or a solicitation of any investment products or other financial product or service, an official confirmation of any transaction, or an official statement of Sender. Subject to applicable law, Sender may intercept, monitor, review and retain e-communications (EC) traveling through its networks/systems and may produce any such EC to regulators, law enforcement, in litigation and as required by law. The laws of the country of each sender/recipient may impact the handling of EC, and EC may be archived, supervised and produced in countries other than the country in which you are located. This message cannot be guaranteed to be secure or free of errors or viruses. References to Sender are references to any subsidiary of Bank of America Corporation. Securities and Insurance Products: * Are Not FDIC Insured * Are Not Bank Guaranteed * May Lose Value * Are Not a Bank Deposit * Are Not a Condition to Any Banking Service or Activity * Are Not Insured by Any Federal Government Agency. Attachments that are part of this EC may have additional important disclosures and disclaimers, which you should read. This message is subject to terms available at the following link: http://www.bankofamerica.com/emaildisclaimer. By messaging with Sender you consent to the foregoing. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition confusion
On 15/02/12 18:14, Sivaram Neelakantan wrote: I was under the impression that you have to define the attributes of the class before using it in an instance. Only in some languages. Python is not one of those. class Point: ... pts in 2d space ... b = Point() b.x =3 b.y =4 print b.y 4 Why is it not throwing an error? This is confusing me a bit. Python allows instance attributes to be added at runtime. In general this is a bad idea IMHO, a dictionary would probably be more appropriate, but there can, very occasionally, be valid uses for it. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition confusion
On Wed, Feb 15, 2012 at 7:14 PM, Sivaram Neelakantan nsivaram@gmail.com wrote: I was under the impression that you have to define the attributes of the class before using it in an instance. Following the book 'thinking in Python', class Point: ... pts in 2d space ... print Point __main__.Point b = Point() b.x =3 b.y =4 print b.y 4 Why is it not throwing an error? This is confusing me a bit. Python is different from static languages like C++. You can add and remove attributes from objects at any time. You do not have to declare, in your class, what kind of attributes it has. An __init__ might seem like it's special in some way, declaring attributes. But it's not, really, it's just another method that gets passed the object it is called on (that would be self). It's only special because it gets called when an object is created, so generally an object is initialized there and attributes are assigned (hence the name init).' HTH, Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition confusion
On Thu, Feb 16 2012,Alan Gauld wrote: [snipped 19 lines] Python allows instance attributes to be added at runtime. In general this is a bad idea IMHO, a dictionary would probably be more appropriate, but there can, very occasionally, be valid uses for it. Thanks for that, I kept thinking that the author had made some typos in the book and was getting progressively confused, till I tried it at the prompt. sivaram -- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition confusion
On 15/02/2012 18:14, Sivaram Neelakantan wrote: I was under the impression that you have to define the attributes of the class before using it in an instance. Following the book 'thinking in Python', class Point: ... pts in 2d space ... print Point __main__.Point b = Point() b.x =3 b.y =4 print b.y 4 Why is it not throwing an error? This is confusing me a bit. sivaram -- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor Your impression is incorrect. This type of behaviour is allowed because of Python's dynamic nature, so the following is fine. class Point: ... pts in 2d space ... b = Point() b.x = 3 b.y = 4 del b.x del b.y b.l = 5 b.m = 6 print b, b.l, b.m __main__.Point instance at 0x02FB89B8 5 6 Also be careful of your terminology. Here we are discussing instance attributes. Class attributes are different in that they are are shared at the class level so. class Point: ... pts in 2d space ... x = 3 ... y = 4 ... a = Point() b = Point() a.x 3 b.y 4 HTH. -- Cheers. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class definition confusion
On 15/02/2012 18:35, Hugo Arts wrote: [snip] An __init__ might seem like it's special in some way, declaring attributes. But it's not, really, it's just another method that gets passed the object it is called on (that would be self). It's only special because it gets called when an object is created, so generally an object is initialized there and attributes are assigned (hence the name init).' HTH, Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor To the OP. Note that __init__ is an initialiser and not a constructor which is __new__, see e.g. http://mail.python.org/pipermail/tutor/2008-April/061426.html -- Cheers. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Nesting
On 02/06/2012 08:17 PM, Greg Nielsen wrote: Hello List, My name is Greg, and while working on a project I've come across a rather interesting problem. I'm trying to create a rough model of a star cluster and all of the stars and planets contained within. Kind of a cool project; hopefully it should work a little like this. I create a Star Cluster object, which goes through a list of positions and decides if it should build a Star System there. If it does, it then creates a Star System object at that position which in turn calls upon and creates several Planet objects to reside inside of it. All in all, about 64 positions to check, on average 24 Star Systems, each with between 2 and 9 planets. So here is the problem, to create an object, you need to assign it to a variable, and you need to know what that variable is to call upon it later, so to have a object build a second object, it would need to somehow create a variable name, and you would somehow have to know what name it picked. Unless perhaps you had a Star Cluster list which had all of your created Star System objects, each with their own list of Planets which you could use list to call upon maybe I have a general grasp on the idea of nesting and calling upon objects which you don't know the name of, but this goes far beyond my level of understanding. Can anyone shed some light on how this would work, or perhaps point me in the right direction of some documentation on this? Thanks for the help, and I hope this is not too difficult of a question. Greg Since you talk of creating a StarCluster object, presumably you know how to make a class. So in the class definition, you can define attributes that each instance has. One of those attributes can be a list. So the list has a name, but not the individual items in the list. Generally, it's best to create an empty list attribute in the initializer of the class. Then whatever class method wants to create these items can simply append them to the list. At this point, you should write some code, and it'll either work, or you'll tell us what part of it you can't understand. -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Nesting
On Mon, Feb 06, 2012 at 08:17:05PM -0500, Greg Nielsen wrote: [...] So here is the problem, to create an object, you need to assign it to a variable, and you need to know what that variable is to call upon it later, so to have a object build a second object, it would need to somehow create a variable name, and you would somehow have to know what name it picked. Unless perhaps you had a Star Cluster list which had all of your created Star System objects, each with their own list of Planets which you could use list to call upon maybe Yes, that's exactly the way to do it. Rather than assigning each object to a name: cluster1 = StarCluster() cluster2 = StarCluster() ... you can work with a list of clusters: clusters = [StarCluster(), StarCluster(), ...] You can then operate on then one at a time. Say you want to do something to the 3rd cluster. Remembering that Python starts counting positions at zero, you would write something like: clusters[2].name = Local Cluster 12345 # give the cluster a name If your StarCluster objects are mutable (and if you don't know what that means, don't worry about it, by default all classes are mutable), you can grab a temporary reference to a cluster while working on it: for cluster in clusters: # work on each one sequentially if cluster.stars == []: print(Cluster %s has no stars. % cluster.name) Here I have assumed that each cluster is given a list of stars. Something like this: class StarCluster(object): def __init__(self): self.name = no name yet self.stars = [] def add_star(self, *args, **kw_args): self.stars.append(Star(*args, **kw_args)) Here I have given the StarCluster a method, add_star, which takes an arbitrary set of arguments, passes them on to the Star class, and adds the resultant star to the list. class Star(object): def __init__(self, name=no name yet, kind=red giant, planets=None): if planets is None: planets = [] self.planets = planets self.name = name self.kind = kind sol = Star( Sol, yellow dwarf, ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] # ha ha, Pluto can bite me ) I hope this helps, -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class vs. instance
On 18/01/12 02:13, Stayvoid wrote: class A: def __init__(self, data): self.data = data print self.data I'm trying to understand this function-like syntax: A('foo').__init__(42) You would not normally call any method with a double underscore pre/poist fix because they are special methods called by Python itself. Thus when you do A('foo') Python actually calls two special methods on class A. First it calls the __new__() method to create an instance of A then it calls __init__() with 'foo' as argument to initialise that instance. You don't need to call init() directly. In fact it may even cause problems if you initialise a class twice. So when you do A('foo').__init__(42) You actually do 3 things: First you create a new instance of A, then you initialise it with 'foo' then you initialise it again with 42. In this case no harm is done because the init)() method just does a double assignment, losing the initial value. But if you were storing the data values in a lkist you would wind up with two values instead of one, which may not be a good thing. A(12).data Here you create another instance of A and initialise it with 12 then you access its data attribute. If you do this in the interpreter the value of data will be printed, if you do it in a program nothing will happen. In both iof the cases above the newly created instances will be garbage collected since they were not assigned to any variable. What are we actually calling this way? You call the constructor __new__(), the initialiser __init__() and you access a data item which calls the accessor __getattr__() Are there any other ways to get the same result? It depends how you define 'the same results'. The same end state can be achieved in several ways. The same methods can be called in several ways, for example you can call init via the class: anAinstance = A('foo') A.__init__(anAinstance, 42) But in general all of these are a bad idea outside of a class/method definition. Don't do it. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class vs. instance
Hello! Here is another one. class A: def __init__(self, data): self.data = data print self.data I'm trying to understand this function-like syntax: A('foo').__init__(42) A(12).data What are we actually calling this way? Are there any other ways to get the same result? Cheers. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class vs. instance
On 01/17/2012 09:13 PM, Stayvoid wrote: Hello! Here is another one. class A: def __init__(self, data): self.data = data print self.data I'm trying to understand this function-like syntax: A('foo').__init__(42) A(12).data What are we actually calling this way? Are there any other ways to get the same result? The first line creates an instance of class A, then immediately calls the method __init__() as though it were a normal function. It then discards the object. You should only call __init__() from within another class' __init__(). It's called automatically when an object is created; leave it at that. You also usually want to keep the instance around, and use it more than once. Otherwise you could just use ordinary functions and dispense with the confusion. A(12) creates an object, then you reference the data attribute of that object, then you throw them both out. Not much use there either. Try something like: obj= A(49) print obj.data obj2 = A(artichoke) obj.data = 99 print obj.data print obj2.data Two more things. Remove the print statement from methods like __init__(), unless it's just for debugging purposes. And add a base class of object to your class definition, so that a new-style class is created. When you get to more advanced usage, it'll make a difference, and you might as well use the version of class that'll still work in Python 3.x. class A(object): . -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class vs. instance
On Sun, Jan 1, 2012 at 8:40 PM, Stayvoid stayv...@gmail.com wrote: Hi there! class Sample: def method(self): pass Sample().method() What's the difference between class __main__.Sample and __main__.Sample instance? Why should I write Sample().method instead of Sample.method? The difference can be illustrated as such: Sample().method bound method Sample.method of __main__.Sample instance at 0x1004d1638 Sample().method() Sample.method unbound method Sample.method Sample.method() Traceback (most recent call last): File stdin, line 1, in module TypeError: unbound method method() must be called with Sample instance as first argument (got nothing instead) That is, the difference between the methods is that the accessed through the instance is also attached to that instance. It will automagically get Sample() passed to it as its first argument (that would be self). The one attached to the class is unbound, which means that you can do this: Sample.method(Sample()) With any Sample instance, of course. This exposes a bit of syntax sugar in python and how classes are really implemented, essentially the fact that, if a is a sample instance, a.method(arg1, arg2, arg3) is actually just Sample.method(a, arg1, arg2, arg3) HTH, Hugo ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class vs. instance
Thanks. I totally get it now. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
David Merrick merrick...@gmail.com wrote Is it possible too have crit1 = Critter(Dave) crit2 = Critter(Sweetie) farm = [crit1,crit2] #List# and then be able to use Critters methods on farm? No, Marc has already answered that. class Critter(object): A virtual pet def __init__(self, name, hunger = 0, boredom = 0): # __ denotes private method def __pass_time(self): self.hunger += 1 self.boredom += 1 self.__str__() def __str__(self): print(Hunger is,self.hunger, Boredom is ,self.boredom) print(Unhappines is ,self.hunger + self.boredom, and Mood is ,self.mood) This is a really bad idea. Please do not do this, it will almost certainly lead to problems later. __str__ should return a string. It should not print anything. Then you can simply call print (self) at the end of the pass_time method or call print (farm[0]) in your external code. HTH, -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
On Sun, Jun 26, 2011 at 7:12 PM, David Merrick merrick...@gmail.com wrote: Is it possible too have crit1 = Critter(Dave) crit2 = Critter(Sweetie) farm = [crit1,crit2] #List# and then be able to use Critters methods on farm? No. farm is a list, and lists don't inherit the methods of the objects inside them (imagine what a nightmare _that_ would be, especially since lists can contain more than one type of object at any given time!) Instead, you would refer to the members of the list: farm[0].talk() farm[1].talk() etc. Only you wouldn't generally hard-code those numbers; instead, you could use the for x in y style: for monster in farm: monster.talk() At this point, monster is one of your Critters. When I need a looping variable for a collection of custom objects, I like to use words that are synonymous with, or at least related to, the name of my custom class. It helps me keep track of what's going on - if I use x and y all over the place, I tend to get confused. You could also use a more traditional, less-Pythonic approach: for x in len(farm): farm[x].talk() But seriously, why would you want to use Python to imitate Visual Basic? By the way, you shouldn't ever need to refer to Dave and Sweetie by their hard-coded variable names, so instead of instead of creating crit1, crit2, why not simply create them as members of the list? farm = [] for critter_name in [Dave, Sweetie]: farm.append(Critter(critter_name)) Now the variables don't have names per se, but you can still refer to them by number if you need one in particular, or you can just loop over the list with for monster in farm. Finally, maybe a dictionary would be more useful/intuitive than a list? farm = [] for critter_name in [Dave, Sweetie]: farm[critter_name] = Critter(critter_name) farm[Dave].talk() I do think that farm is going to be a little misleading as a name for a collection of Critters; might I suggest herd or swarm? Just a thought... ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
David Merrick merrick...@gmail.com wrote class Critter(object): def __init__(self, name, hunger = 0, boredom = 0): def __pass_time(self): def __str__(self): @property def mood(self): def talk(self): def eat(self): def play(self): class Farm(Critter): I still don't think a Farm is a type of Critter... def __init__(self,farmlet): Critter.__init__(self,farmlet) This will set the name to farmlet, which I don't think you want. def talk(self,farmlet): You don't need to pass farmlet in since the class has farmlet stored inside it. You can access farmlet with self.farmlet. for critter in farmlet: print(Hello) Critter.talk(farmlet) You want the instance to talk not the class. So you need to use critter.talk() And the talk method does not take any arguments except self. What you are doing here is calling the class method with an instance value of farmlet. ie self in that method gets the value of farmlet. def main(): crit1 = Critter(Sweetie) crit2 = Critter(Dave) farmlet = [crit1,crit2] f = Farm(farmlet) choice = None while choice != 0: print \ ( Critter Caretaker 0 - Quit 1 - Listen to your critter 2 - Feed your critter 3 - Play with your critter ) choice = input(Choice: ) print() # exit if choice == 0: print(Good-bye.) # listen to your critter elif choice == 1: f.talk(farmlet) # feed your critter elif choice == 2: f.eat(farmlet) Note that f.eat is a method you inherit from Critter. The Critter method does not take any arguments so this will fail. # play with your critter elif choice == 3: f.play(farmlet) Same with f.play() Traceback (most recent call last): File D:/David/Python/programs/critter_farm3.py, line 72, in talk Critter.talk(farmlet) File D:/David/Python/programs/critter_farm3.py, line 38, in talk print(I'm, self.name, and I feel, self.mood, now.\n) AttributeError: 'list' object has no attribute 'name' This is because you are accessing the method via the class and passing farmlet as the instance value rather than sending the message to the innstance directly. Use critter.talk() # and no farmlet needed! HTH, -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
David, 2011/6/22 David Merrick merrick...@gmail.com: # listen to your critter elif choice == 1: for critter in farmlet: farmlet.talk() You want to call .talk() on your critter instance which has the .talk() method, not on farmlet (which is a list as the error message states) Traceback (most recent call last): File I:/Python/programs/critter_farm4.py, line 117, in module main() File I:/Python/programs/critter_farm4.py, line 103, in main farmlet.talk() AttributeError: 'list' object has no attribute 'talk' You will probably have a problem when calling talk() because it references to the farmlet variable which doesn't exist in the scope of your .talk() method. HTH, -- Alex | twitter.com/alexconrad ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
Just to add a little to Alexandre's answer. You can keep most of the code the same just add in farmlet[0].eat() farmlet[1].eat() and it will be okay... kinda. Or you could rewrite it and do it another way... I'm guessing that you are using python 3 by your print statements, so I don't think you need the int() around your input, even in python.2x input() was safe for numbers I believe (the whole list will rip my throat out if I'm wrong anyways, lol), but in your while loop around line 82 you have all the conditions responding to a string, even thought you explicitly changed the input to an integer. if choice == 0 instead of if choice == 0: so I got a continual output of ('\nSorry, but', 3, isn't a valid choice.) Now this does not get your program running the way you want it to, but it will start you off making the corrections you need. Just some things to think about, in line 113, when did you define class f? in line 102, what are you trying to do, and are you telling it the right thing? since you have 2 (or possibly more) critters you are taking care of, how does the player know which one he is feeding / talking to / playing with in your farmlet? Anyways best of luck in your program, sounds pretty cool... What is it about you... that intrigues me so? From: Alexandre Conrad alexandre.con...@gmail.com To: David Merrick merrick...@gmail.com Cc: tutor@python.org Sent: Wednesday, June 22, 2011 6:48 PM Subject: Re: [Tutor] Class methods David, 2011/6/22 David Merrick merrick...@gmail.com: # listen to your critter elif choice == 1: for critter in farmlet: farmlet.talk() You want to call .talk() on your critter instance which has the .talk() method, not on farmlet (which is a list as the error message states) Traceback (most recent call last): File I:/Python/programs/critter_farm4.py, line 117, in module main() File I:/Python/programs/critter_farm4.py, line 103, in main farmlet.talk() AttributeError: 'list' object has no attribute 'talk' You will probably have a problem when calling talk() because it references to the farmlet variable which doesn't exist in the scope of your .talk() method. HTH, -- Alex | twitter.com/alexconrad ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
michael scott jigenbak...@yahoo.com wrote you are using python 3 by your print statements, so I don't think you need the int() around your input, Yes he does because in Python 3 input is the same as raw_input in Python 2 even in python.2x input() was safe for numbers I believe (the whole list will rip my throat out if I'm wrong anyways rip, rip, rip. :-) In Python 2 input could be used for numbers but it was not safe, which is why input was effectively removed in Python 3 and raw_input renamed to input. In Python 2 input() evaluated whatever was typed as a Python expression which made it very unsafe. -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class methods
David Merrick merrick...@gmail.com wrote Can someone show me how to code this correctly please? We've been doing that but you are still making some very basic mistakes which reflect a deep misunderastanding of what you are doing. You really should take several steps back and review the use of variables and functions and then reread the introductory material on classes and objects. Until you get the basics right you will struggle and even if somebody fixes all the issues in this code, the minute you try another program all the same problems will bite you. That having been said I'll make some comments: class Critter(object): A virtual pet def __init__(self, name, hunger = 0, boredom = 0): self.name = name self.hunger = hunger self.boredom = boredom This is OK. # __ denotes private method def __pass_time(self): self.hunger += 1 self.boredom += 1 self.__str__() The last line does nothing useful. (It prints stuff just now but that's because of a conceptual fault in your str method. What you should really be saying here is: print (self) def __str__(self): print(Hunger is,self.hunger, Boredom is ,self.boredom) print(Unhappines is ,self.hunger + self.boredom, and Mood is ,self.mood) __str__ methods are supposed to return a string which can be used (or printed) by other code. They should not print anything themselves. This should do something like: return Hunger is %s, Boredom is %s Unhappines is %s and Mood is%s % ( self.hunger, self.boredom, self.hunger+self.boredom, self.mood) @property def mood(self): unhappiness = self.hunger + self.boredom if unhappiness 5: m = happy elif 5 = unhappiness = 10: m = okay elif 11 = unhappiness = 15: m = frustrated else: m = mad return m OK def talk(self): for critter in farmlet: print(I'm, self.name, and I feel, self.mood, now.\n) self.__pass_time() Problem: What is farmlet here? There is no farmlet in the method. There is no self.farmlet you can access. So now your class is tied to the external farmlet variable in the global scope, making your class pretty much useless in any other context. Also it will print the same message as many times as there are critters in farmlet - 2 in this case. But the message won't change because self still only applies to the current object. You are iterating over the critters in your main() function, you don't need to do it inside the critter itself. Each critter should only comment on its own state. I'd also prefer that this returned a string too because putting print statements inside methods limits the usefulness of the class. How would it work in a GUI version for example? Better to return a string and print that where you call it. def eat(self): food = int(input(Enter how much food you want to feed your critter: )) print(Brruppp. Thank you.) self.hunger -= food # hunger = 0 at iniatition # self.hunger = self.boredom - food if self.hunger 0: self.hunger = 0 self.__pass_time() OK, I think def play(self): fun = int(input(Enter how much fun you want your critter to have: )) print(Wheee!) self.boredom -= fun # boredom = 0 at iniatition # self.boredom = self.boredom - fun if self.boredom 0: self.boredom = 0 self.__pass_time() OK, I think def main(): crit1 = Critter(Sweetie) crit2 = Critter(Dave) farmlet = [crit1,crit2] OK so far, we have a list with two Critters choice = None while choice != 0: print \ ( Critter Caretaker 0 - Quit 1 - Listen to your critter 2 - Feed your critter 3 - Play with your critter ) choice = input(Choice: ) print() Also OK we now have a choice and a loop. if choice == 0: print(Good-bye.) And we exit so the program eventually stops, which is good. elif choice == 1: for critter in farmlet: farmlet.talk() But here we are asking the list to do stuiff which is not good. It is the critters that talk. So you need to send talk() to the critter not the list: for critter in farmlet: critter.talk() # feed your critter elif choice == 2: farmlet.eat() Again lists can't eat, you need to feed weither an individual crittter - get the user to choose which? - or feed all your critters using the same code pattern as for talk above. # play with your critter elif choice == 3: f.play(farmlet) You don't have an f and you don't now have a play method or function that takes a farmlet as
Re: [Tutor] class question
Karim karim.liat...@free.fr wrote Program towards interface that means you have to use inheritance. Just to be picky, you can program by interface without using inheritance. Inheritance is only needed to implement interfaces in languages like C++. In Python (and other dynamically bound OOP languages) you can use polymorphism without inheritance. -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Sure, but I come from java world and 1 inheritance is allowed but we can implement multiple interfaces. I like to use Abstract classes in Python then inherit and implement abstract method like in java (at least that's all I remember from Java experience). Indeed I was too direct everybody has the same style. Regards Karim On 01/26/2011 12:08 PM, Alan Gauld wrote: Karim karim.liat...@free.fr wrote Program towards interface that means you have to use inheritance. Just to be picky, you can program by interface without using inheritance. Inheritance is only needed to implement interfaces in languages like C++. In Python (and other dynamically bound OOP languages) you can use polymorphism without inheritance. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
I know the the law of Murphy. But this one is a must-have.:-) Regards Karim * One way to reduce coupling is with the Law of Demeter: if you want your dog to walk, don't talk to your dog's legs. You will only confuse the dog and it won't get anywhere. http://en.wikipedia.org/wiki/Law_of_Demeter Hope this helps. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Elwin Estle wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Yes. Or no. It's impossible to answer that question definitively without knowing more about what it all is. But I can give some general advice: * Python isn't Java. Don't feel that you must use classes. If your problem is better solved using a procedural or functional approach, go right ahead and use it. Classes aren't compulsory. * The standard model which you should use it: verbs - functions or methods nouns - classes or attributes You should be able to answer the question What *thing* does your class represent?. (The answer can be an abstract thing, but it should be a thing.) If you can't answer that question, then you shouldn't use a class. You should solve the problem using stand-alone functions. * Think about is-a and has-a relationships: == The class in question, does, in fact, deal with a thing. The problem is, the thing is highly mutable. The is-a and the has-a changes. Here is the scenario: A raw casting comes into a factory. It is listed as such. When machined, this part number changes to a different part number. The raw casting has no quality related stuff, but the machined casting does, and it can have more than one quality related thing. ...because, the raw casting may go through multiple operations to get to it's final state. It may get machined on a lathe, then be transferred to a CNC machining station where a bolt circle may be drilled and tapped into it. Each of those operations on separate machines will have a different set of quality checks associated with it. ...or it might be a part that goes from a raw casting to a sort of mini-assembly such as a rocker lever (if you know what that is), so we have raw casting = one part number, then it gets a bushing pressed into it = another part number, then it gets a threaded insert = another part number, but it is still the same thing, and each one of those steps may have some sort of quality check involved. Lets complicate things even further. One raw casting may be machined into multiple part numbers. Perhaps the only thing that changes is the location of a single hole. But again, each one of those part numbers may go through multiple machining operations on different machines, with different quality checks. This is done through something called a tabbed blueprint, wherein there is a master number, but there are tabs indicating that if you changes such and such feature, then the part number isn't the master number, but the tabbed number. So, in essence, there's a sort of network of is-a and has-a information. My idea was to, instead of having just a single part class, to have a sort of component aggregate class, which would cover not only single parts, but assemblies of parts. So, even if a part was as simple as a raw casting that is just machined into a finished part and that's it, it would still be treated as a sort of assembly, with the raw casting being a component of the finished part number, if that makes sense. So there's all this information associated with a given part. I am thinking it has a sort of tree structure. I am just wondering if some of the branches of the tree should be separate classes that are then tied into the trunk of the master class, or if the whole thing should be a tree into and of itself. ...and yeah, I know, it's kind of a complex problem for a newbie to be thinking about. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
A raw casting comes into a factory. It is listed as such. When machined, this part number changes to a different part number. The raw casting has no quality related stuff, but the machined casting does, and it can have more than one quality related thing. ...because, the raw casting may go through multiple operations to get to it's final state. It may get machined on a lathe, then be transferred to a CNC machining station where a bolt circle may be drilled and tapped into it. Each of those operations on separate machines will have a different set of quality checks associated with it. ...or it might be a part that goes from a raw casting to a sort of mini-assembly such as a rocker lever (if you know what that is), so we have raw casting = one part number, then it gets a bushing pressed into it = another part number, then it gets a threaded insert = another part number, but it is still the same thing, and each one of those steps may have some sort of quality check involved. Lets complicate things even further. One raw casting may be machined into multiple part numbers. Perhaps the only thing that changes is the location of a single hole. But again, each one of those part numbers may go through multiple machining operations on different machines, with different quality checks. This is done through something called a tabbed blueprint, wherein there is a master number, but there are tabs indicating that if you changes such and such feature, then the part number isn't the master number, but the tabbed number. So, in essence, there's a sort of network of is-a and has-a information. My idea was to, instead of having just a single part class, to have a sort of component aggregate class, which would cover not only single parts, but assemblies of parts. So, even if a part was as simple as a raw casting that is just machined into a finished part and that's it, it would still be treated as a sort of assembly, with the raw casting being a component of the finished part number, if that makes sense. So there's all this information associated with a given part. I am thinking it has a sort of tree structure. I am just wondering if some of the branches of the tree should be separate classes that are then tied into the trunk of the master class, or if the whole thing should be a tree into and of itself. ...and yeah, I know, it's kind of a complex problem for a newbie to be thinking about. Here is my two-cents. This code is untested. Import statements haven't been included, there could be syntax errors, etc etc etc. What I did was switching off the part_number attribute in the Thing class. For the functions that do stuff to the thing instance, I appended a part-number (assuming new part number = master number + doing stuff number). The quality functions will check for that part number before proceeding with the checks. class Thing: # single part class def __init__(self,part_number='12345'): # 12345 is a default part number self.part_number=part_number def routeThing(thing): try: thing.part_number.append('-someRoutingPartNumber') do routing exception AttributeError (e): e.printStackTrace() print Router was not applied to thing def checkQualityRoute1(thing): if hasattrib(thing,part_number) (thing.part_number.find('-someRoutingPartNumber'): do quality checks else: print Thing has not be routed yet def checkQualityRoute2(thing): if hasattrib(thing,part_number) (thing.part_number.find('-someRoutingPartNumber'): do quality checks else: print Thing has not be routed yet continue for all of the functions that you might need HTH, -Tino ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
class Raw --- class Processor --- class Final 2011/1/26 Tino Dai obe...@gmail.com A raw casting comes into a factory. It is listed as such. When machined, this part number changes to a different part number. The raw casting has no quality related stuff, but the machined casting does, and it can have more than one quality related thing. ...because, the raw casting may go through multiple operations to get to it's final state. It may get machined on a lathe, then be transferred to a CNC machining station where a bolt circle may be drilled and tapped into it. Each of those operations on separate machines will have a different set of quality checks associated with it. ...or it might be a part that goes from a raw casting to a sort of mini-assembly such as a rocker lever (if you know what that is), so we have raw casting = one part number, then it gets a bushing pressed into it = another part number, then it gets a threaded insert = another part number, but it is still the same thing, and each one of those steps may have some sort of quality check involved. Lets complicate things even further. One raw casting may be machined into multiple part numbers. Perhaps the only thing that changes is the location of a single hole. But again, each one of those part numbers may go through multiple machining operations on different machines, with different quality checks. This is done through something called a tabbed blueprint, wherein there is a master number, but there are tabs indicating that if you changes such and such feature, then the part number isn't the master number, but the tabbed number. So, in essence, there's a sort of network of is-a and has-a information. My idea was to, instead of having just a single part class, to have a sort of component aggregate class, which would cover not only single parts, but assemblies of parts. So, even if a part was as simple as a raw casting that is just machined into a finished part and that's it, it would still be treated as a sort of assembly, with the raw casting being a component of the finished part number, if that makes sense. So there's all this information associated with a given part. I am thinking it has a sort of tree structure. I am just wondering if some of the branches of the tree should be separate classes that are then tied into the trunk of the master class, or if the whole thing should be a tree into and of itself. ...and yeah, I know, it's kind of a complex problem for a newbie to be thinking about. Here is my two-cents. This code is untested. Import statements haven't been included, there could be syntax errors, etc etc etc. What I did was switching off the part_number attribute in the Thing class. For the functions that do stuff to the thing instance, I appended a part-number (assuming new part number = master number + doing stuff number). The quality functions will check for that part number before proceeding with the checks. class Thing: # single part class def __init__(self,part_number='12345'): # 12345 is a default part number self.part_number=part_number def routeThing(thing): try: thing.part_number.append('-someRoutingPartNumber') do routing exception AttributeError (e): e.printStackTrace() print Router was not applied to thing def checkQualityRoute1(thing): if hasattrib(thing,part_number) (thing.part_number.find('-someRoutingPartNumber'): do quality checks else: print Thing has not be routed yet def checkQualityRoute2(thing): if hasattrib(thing,part_number) (thing.part_number.find('-someRoutingPartNumber'): do quality checks else: print Thing has not be routed yet continue for all of the functions that you might need HTH, -Tino ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Karim karim.liat...@free.fr wrote Sure, but I come from java world and 1 inheritance is allowed but we can implement multiple interfaces. I like to use Abstract classes in Python then inherit and implement abstract method like in java (at least Sure and that is the normal way of doing it. Not least because you can inherit non abstract methods too! But there is a danger of forgetting that inheritance is not the *only* way. Thats all I was pointing out, inheritance is the norm but not essential. -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Elwin Estle chrysalis_reb...@yahoo.com wrote The class in question, does, in fact, deal with a thing. The problem is, the thing is highly mutable. You can mutate objects, that is not a problem. But you need to be sure you need to. Is this really a series of different types of casting or a single Workpiece going through a sequence of Actions each Action having a set of quality data associated? If so it may be that you have a single Workpiece class and a relatively small heirarchy of Actions. A raw casting comes into a factory. It is listed as such. When machined, this part number changes to a different part number. The raw casting has no quality related stuff, but the machined casting does, Is it the casting or the machining that has the quality related data? ie Is it casting specific or operation specific? ...because, the raw casting may go through multiple operations to get to it's final state. Do you know in advance what these operations will be? Can you assign a WorkPlan to the Workpiece? Each step of the plan having an associated Action? Each of those operations on separate machines will have a different set of quality checks associated with it. So here we clearly say it is the Action that has the data associated... ...or it might be a part that goes from a raw casting to a sort of mini-assembly such as a rocker lever ... but it is still the same thing, and each one of those steps may have some sort of quality check involved. So a workpice can consist of other WorkPieces. And again tyhe Actions associated have quality data Lets complicate things even further. One raw casting may be machined into multiple part numbers. Is that true? Or is it one type of casting? Each instance of casting will surely onmly go through one specific set of actions? If we treat them all as generic workpieces then the Actions are different but the workpiece concept remains constant? Or, are we saying that a single original workpiece can be cut into several distinct workpieces? Again thats not necessarily a problem, objects can clone themselves and have the clones diverge thereafter. Perhaps the only thing that changes is the location of a single hole. But again, each one of those part numbers may go through multiple machining operations on different machines, with different quality checks. This is done through something called a tabbed blueprint, wherein there is a master number, but there are tabs indicating that if you changes such and such feature, then the part number isn't the master number, but the tabbed number. I'm not sure I follow that bit. So, in essence, there's a sort of network of is-a and has-a information. I see a lot of has-a but very little is-a at this stage. In fact I don't see any is-a yet, althopugh I can see where some might emerge in the future. have a sort of component aggregate class, which would cover not only single parts, but assemblies I think that will be essential. if a part was as simple as a raw casting that is just machined into a finished part and that's it, it would still be treated as a sort of assembly, One of the key features of assemblies is that they should scale down to a single item just as easily as up to many parts. So there's all this information associated with a given part. I am thinking it has a sort of tree structure. I think there probably is and you should look into the composite pattern to build that. I am just wondering if some of the branches of the tree should be separate classes Probably, but not so many different classes as you currently suspect. ...and yeah, I know, it's kind of a complex problem for a newbie to be thinking about. Yes, very challenging. This is one of the kinds of problem where the best solution is probably not be the first one you think of. But you won't know that till after you try building it! My proposal is only a guess based on a quick review of your description and no local domain knowledge... You may also find it useful to think through the state model for your castings/workpieces. That may help to constrain the number of Actions/operations required. -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
--- On Wed, 1/26/11, Alan Gauld alan.ga...@btinternet.com wrote: From: Alan Gauld alan.ga...@btinternet.com Subject: Re: [Tutor] class question To: tutor@python.org Date: Wednesday, January 26, 2011, 1:10 PM Is this really a series of different types of casting or a single Workpiece going through a sequence of Actions each Action having a set of quality data associated? If so it may be that you have a single Workpiece class and a relatively small heirarchy of Actions. No, there are multiple castings, anywhere from smallish parts you can hold in the palm of your hand, up to engine blocks weighing nearly 2 tons. Is it the casting or the machining that has the quality related data? ie Is it casting specific or operation specific? The casting can have quality data associated with it, tho rarely. If there is a machining issue that can be traced back to defective castings, then yes (but we don't really have any process in place for this, normally that sort of thing is the casting supplier's problem). Normally, tho, it is the machining that has the associated quality data., i.e., measure a 2.500 machined bore with a +/- .001 tolerance, using such and such gage, giving some result (like 2.503, for example), measured on such and such date by such and such machine operator. Various bits like this will be associated with a given machining operation. Sometimes machining operations are all done on a single machine, sometimes they span multiple machines. Do you know in advance what these operations will be? Can you assign a WorkPlan to the Workpiece? Each step of the plan having an associated Action? I would say yes. However, and this ties in with something you ask further down, sometimes that plan may sort of overlap For example, say we have a raw casting, 3402963R, that when machined, becomes part # 3402963. But that same raw casting may also be machined into another part number # 3332965, simply by adding or omitting hole or some other feature. So, I suppose one could have separate plans for each finished part number, in which case there might be some duplication of things for each plan. Each of those operations on separate machines will have a different set of quality checks associated with it. So here we clearly say it is the Action that has the data associated... ...or it might be a part that goes from a raw casting to a sort of mini-assembly such as a rocker lever ... but it is still the same thing, and each one of those steps may have some sort of quality check involved. So a workpice can consist of other WorkPieces. And again tyhe Actions associated have quality data Lets complicate things even further. One raw casting may be machined into multiple part numbers. Is that true? Or is it one type of casting? Each instance of casting will surely onmly go through one specific set of actions? If we treat them all as generic workpieces then the Actions are different but the workpiece concept remains constant? Or, are we saying that a single original workpiece can be cut into several distinct workpieces? Again thats not necessarily a problem, objects can clone themselves and have the clones diverge thereafter. Yes, that is the case, as described above. This is done through something called a tabbed blueprint, wherein there is a master number, but there are tabs indicating that if you changes such and such feature, then the part number isn't the master number, but the tabbed number. I'm not sure I follow that bit. Say you have a master part, # 3245671, this is sort of a primary machined number. On the blueprint for this part, there will be certain features that don't have any dimensional information, but instead have a callout of some kind, i.e., Hole D, or somesuch. At the top of the blueprint is a tab block that is a table of alternate part numbers, vs these named features. Each of these part numbers will have differing information as to the nature of Hole D. Perhaps the size of Hole D differs from one part number to the next, or perhaps it is omitted all together. It goes along wth the one casting makes multiple part numbers thing described above. In and of itself, this perhaps may not seem that complicated...but the blueprints aren't filed under the the actual part number for a given tabbed part, but under the master number. So...you may have part 3458760, but the blueprint for it is filed under 3245671, so you have to go hunt up that blueprint, then hunt up the information on it that describes the actual part in question. All this ties in to your quality control documentation. You have to make sure that when you check a hole diameter, you are checking the correct one as per the tabbed print. Why not have separate prints for each part number? This was originally a convenience/cost saving thing, I suspect. Back in the days when blueprints were hand drawn, having someone do a separate print for all the part numbers
Re: [Tutor] Class Docs - how much is too much?
On 1/26/2011 11:03 AM Tim Johnson said... FYI: I'm currently using version 2.6.5 I've developed a module which necessitates a very large amount of documentation. At this point all of the documentation is in the class docstring. I'm thinking that perhaps I should pare down the docstring and deliver specific documentation topics with object methods. Example: ## Instantiation examples o.intialize() ## configuration code to copy and paste into file o.configuration() ## Internal processes o.internals() ## ... etc. ## Docstring would include instructions for implementing such ## methods. :) Perhaps there is a PEP for this and a link to such a PEP would suffice. Yep -- google python pep docstring and you get http://www.python.org/dev/peps/pep-0257/ Emile ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class Docs - how much is too much?
* Emile van Sebille em...@fenx.com [110126 12:30]: On 1/26/2011 11:03 AM Tim Johnson said... I've developed a module which necessitates a very large amount of documentation. At this point all of the documentation is in the class docstring. I'm thinking that perhaps I should pare down the docstring and deliver specific documentation topics with object ... :) Perhaps there is a PEP for this and a link to such a PEP would suffice. Yep -- google python pep docstring and you get http://www.python.org/dev/peps/pep-0257/ Thank you. That's all I need. -- Tim tim at johnsons-web.com or akwebsoft.com http://www.akwebsoft.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
On 01/25/2011 06:26 PM, Elwin Estle wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Seems to me like the one large class would be clearer in some ways. I have something I am trying to do that have somewhere in the neighborhood of 20 attributes that all relate together, however there are sort of clumps of attributes that have a sub-relationship to each other and I wondered if they should be their own class, but I am not sure, assuming that is a good idea, how these smaller classes might work together. I have only the foggiest notion of inheritance and I'd kind of like to stay away from that aspect of things until I get a better grasp of individual classes. If you're just learning, go ahead and make a 'do it all' class. Don't do it later in your growth as a programmer though. Inheritance works like this: class Parent: def __init__(self): print Parent initialised class Child(Parent): pass The parenthesis set the superclass or parent class. If you now do: c = Child() You should see Parent initialised printed to the terminal. It makes all the 'parents' methods available to it. You can think of it as copying all the code from the parent class into the child class. You can overwrite the methods too: class Animal: def speak(self): print self.noise class Pig(Animal): def __init__(self): self.noise = Oink! pig = Pig() pig.speak() Hope it helped, ~Corey ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
On Tue, Jan 25, 2011 at 3:26 PM, Elwin Estle chrysalis_reb...@yahoo.com wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Seems to me like the one large class would be clearer in some ways. I have something I am trying to do that have somewhere in the neighborhood of 20 attributes that all relate together, however there are sort of clumps of attributes that have a sub-relationship to each other and I wondered if they should be their own class, but I am not sure, assuming that is a good idea, how these smaller classes might work together. I have only the foggiest notion of inheritance and I'd kind of like to stay away from that aspect of things until I get a better grasp of individual classes. For me, the question of one big class/multiple smaller classes comes down to reusability. If you find yourself writing the same code over and over again (or cutting/pasting big blocks of code), you should probably break up your classes. -- www.fsrtechnologies.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Elwin Estle chrysalis_reb...@yahoo.com wrote Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Usually the latter. But remember that classes model objects. Objects usually have a direct relationship to some kind of real world entity - even if its an abstract conceptual entity. So if the attributes and behaviours are all exhibited by the thing you are modelling then they should maybe stay together. But uasually the big thing can be modelled as a composition of smaller things... Seems to me like the one large class would be clearer in some ways. Very rarely is a big lump of code clearer than several small single purpose lumps of code. And big lumps of code are nearly always harder to reuse - one of the other reasons to create classes... I have something I am trying to do that have somewhere in the neighborhood of 20 attributes that all relate together, however there are sort of clumps of attributes that have a sub-relationship to each other Without specifics we can't be sure. But it sounds like you have a composite structure. OTOH 20 attributes is not enormous - 200 would be, but not 20. But even 20 is enough to challenge. I have only the foggiest notion of inheritance It doesn't sound like inheritance is an issue here. It sounds like we are talking about composition. But without specific details we can't be sure. Remember that the thing that defines a class should be its operations not its data. Do these smaller clumps of attributes have common behaviour associated with them? The data should only be there to support the operations. HTH, -- Alan Gauld Author of the Learn to Program web site http://www.alan-g.me.uk/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Hello, Design Patterns is the key for code reuse and problem solving. Indeed you have to separate your objects (classes) to use it. The god class is like a script with only one function: not very flexible and easy to debug. Program towards interface that means you have to use inheritance. Try to determine the objects you need for your problem and next step is how arrange it together (relational). Regards Karim On 01/26/2011 01:28 AM, Marc Tompkins wrote: On Tue, Jan 25, 2011 at 3:26 PM, Elwin Estlechrysalis_reb...@yahoo.com wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Seems to me like the one large class would be clearer in some ways. I have something I am trying to do that have somewhere in the neighborhood of 20 attributes that all relate together, however there are sort of clumps of attributes that have a sub-relationship to each other and I wondered if they should be their own class, but I am not sure, assuming that is a good idea, how these smaller classes might work together. I have only the foggiest notion of inheritance and I'd kind of like to stay away from that aspect of things until I get a better grasp of individual classes. For me, the question of one big class/multiple smaller classes comes down to reusability. If you find yourself writing the same code over and over again (or cutting/pasting big blocks of code), you should probably break up your classes. -- www.fsrtechnologies.com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Elwin Estle wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? Yes. Or no. It's impossible to answer that question definitively without knowing more about what it all is. But I can give some general advice: * Python isn't Java. Don't feel that you must use classes. If your problem is better solved using a procedural or functional approach, go right ahead and use it. Classes aren't compulsory. * The standard model which you should use it: verbs - functions or methods nouns - classes or attributes You should be able to answer the question What *thing* does your class represent?. (The answer can be an abstract thing, but it should be a thing.) If you can't answer that question, then you shouldn't use a class. You should solve the problem using stand-alone functions. * Think about is-a and has-a relationships: - if x is a Foo, then use a class Foo and make x an instance of Foo - if x has a Foo, then give x an attribute x.foo which is a Foo * Classes should represent a *single* well-defined thing. That might be a compound thing, or a collection of things -- the class represents the entire collection. If the thing is made of parts, each part could be represented by an attribute. This is okay: class Coffee: def __init__(self): self.style = 'white' self.milk = 'full cream' self.sugars = 1 self.size = 'regular' class Pie: def __init__(self): self.kind = 'cherry' self.slices = 1 self.with_cream = False class SpecialOfTheDay: def __init__(self): self.drink = Coffee() self.snack = Pie() But don't design a class like this: class CoffeeAndPie: def __init__(self): self.style = 'white' self.milk = 'full cream' self.sugars = 1 self.size = 'regular' self.kind = 'cherry' self.slices = 1 self.with_cream = False One slice of coffee? Oh really? * Classes should be more general rather than too specific. But don't go crazy and make it so abstract that you run out of air to breathe, and nobody can understand what the hell the class is for: http://www.joelonsoftware.com/articles/fog18.html * Coupling is usually bad. Aim to reduce coupling, unless you have a good reason for wanting strongly coupled systems. What's coupling? A key and a lock are *highly* coupled: only one key will fit the lock, and no other key will do the job. But, say, a knife and a steak are loosely coupled. Any sharp knife will cut a steak. Sure, some knives are better than others, but at a pitch, you could even use a blunt butter-knife and a lot of effort. Another example: your clothes iron and ironing board have very loose coupling. You can use any iron on any board, and it will be just fine. But the memory cards in your computer are moderately coupled with the motherboard: only some memory cards will fit. You can't use a 1980 64K memory card in a 2011 motherboard. But provided the memory will fit, it doesn't matter which card you use. * One way to reduce coupling is with the Law of Demeter: if you want your dog to walk, don't talk to your dog's legs. You will only confuse the dog and it won't get anywhere. http://en.wikipedia.org/wiki/Law_of_Demeter Hope this helps. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
Corey Richardson wrote: On 01/25/2011 06:26 PM, Elwin Estle wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? If you're just learning, go ahead and make a 'do it all' class. Don't do it later in your growth as a programmer though. Learn bad habits first, then spend years trying to break them! *wink* -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class question
On 01/25/2011 08:50 PM, Steven D'Aprano wrote: Corey Richardson wrote: On 01/25/2011 06:26 PM, Elwin Estle wrote: Is it better to have one large sort of do it all class, or break the larger class up into smaller classes? If you're just learning, go ahead and make a 'do it all' class. Don't do it later in your growth as a programmer though. Learn bad habits first, then spend years trying to break them! *wink* Hey, gotta learn the concepts first, right? ;-) I remember my first substantial program, hangman! Quite a mess. Excerpt: def getlist3(self): list3 = [] for i in range(5): list3.append(self.gameWord[i]) self.list3 = list3 I don't even remember what list3 is. I have a whole function for a list comprehension! self.list3 = [char for (idx, char) in enumerate(gameWord) if gameWord.index(char, idx) 5] (list3 happened to be the hint characters given, remembered while doing) Just proof that it doesn't have to take years, it could take months. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
Hello, Fine that you are in a arque But can we come back to my problem. How can I take care that test2 can be initialized. Roelof ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On 2:59 PM, Roelof Wobben wrote: Hello, Fine that you are in a arque But can we come back to my problem. How can I take care that test2 can be initialized. Roelof You had this code, and got the following error: class zoeken() : pass def __len__(self): return 0 def __str__(self): return test2 def find(self, strng, ch, start, stop): index = start while index len(strng) and index stop: if strng[index] == ch: return index index += 1 return -1 test = zoeken() test.woord = tamara test2 = zoeken.find(test, a, 1,5) print test(test2) But now I get this message : Traceback (most recent call last): File C:\Users\wobben\workspace\oefeningen\src\test.py, line 20, inmodule test2 = zoeken.find(test, a, 1,5) TypeError: find() takes exactly 5 arguments (4 given) The immediate answer is that 1) you are calling the find method with the class as the first argument, while it was declared with 'self'. 2) you never pass a string to be searched, so there's nothing useful to be passed to strng. It's the second problem that causes the error, but the first one is tied with it. You can fix the immediate syntax error by passing the string explicitly. test2 = test.find(tamara, a, 1, 5) The real problem though is one of design, or intent. You're assigning that tamara to an attribute of a particular instance of zoeken(). So did you mean that find() would look there for it? If that were the case, the find declaration should change to: def find(self, ch, start, stop): and naturally, the reference to strng[index] should change to self.woord[index] There are several things wrong with the find() method, and with the __str__() method, but the first question that needs answering is What does a zoeken (please capitalize it, to follow Python conventions) object represent? What are its data attributes going to mean? Since it's not English, I don't get a clue from the name, but normally I'd get one from the __init__() method, which you omitted. My convention is to initialize all attributes in the __init__() method, even if they're not always used. But if that's undesirable for some reason, then at least comment on them there. DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
I looked up the word zoeken -- it means find in English. I looked up the chapter and exercise in the online text How to think like a computer scientist Its a good tutorial. I think the OP seems to get confused on basic concepts. Here is my stab at the exercise: #!/usr/bin/env python This exercise is to take the find function, alter it so that it can specify an end point for the search. It is problem 2 at the end of this chapter: http://openbookproject.net/thinkcs/python/english2e/ch15.html The author notes that end should default to len(str), but it can't since default parameters are initialized when the function is defined and not when it is invoked. # this is from the author's text def find(str, ch, start=0): index = start while index len(str): if str[index] == ch: return index index = index + 1 return -1 # this I believe is the concept the author was looking to get the reader to understand def find2(str, ch, start=0, end = None): if end == None: end = len(str) index = start while index end: if str[index] == ch: return index index = index + 1 return -1 -- Joel Goldstick ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On Sun, 26 Sep 2010 02:26:25 pm David Hutto wrote: On Sat, Sep 25, 2010 at 9:16 PM, Steven D'Aprano st...@pearwood.info wrote: On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote: Since I had nothing else to do, but practice, this looks much better: def find(word, search): if search in word: print True else: print False [...] OP wanted to find if a in b. Does my function do that?...Yep I didn't say that the function did the wrong thing, I said the name was misleading for what it actually did. Why didn't you call the function len(), or deleteItemsFromPage()? Because those names would be misleading, deceptive and silly. And so is calling a function find() when it does something completely different from the commonly understood meaning of the word find. When you find something, you know where it is afterwards. In the context of text searches, that means returning an offset to where the target is found, or something similar. That's what str.find() does, and regular expressions, and list.index(). Your find function is a membership test, which is what the `in` operator is for. Yes, we found your terms on the Internet, but we won't tell you where. If you would like to find something else, we won't tell you where that is either. It's not supposed to be a four line version of Google. I didn't say it was. I tried to inject a little humour into the email, but it clearly didn't work. [...] Even this is slightly misleading, because text doesn't need to be an actual string. It could be any sequence, such as a list. But this gives the *intention* of the function, which is to do text searches. So this is (in my opinion) an acceptable compromise between intention and generality. Semantics, are only important to those who didn't write it. Semantics means meaning. If you are trying to tell me that the meaning of programs -- their *purpose* -- is unimportant, that it doesn't matter what a function does, I'm afraid you'll have your work cut out to convince me. The most important reader of your functions is... you. The function might be fresh in your mind *today*, but tomorrow? Next week? Six months from now when you discover a bug in your program and are trying to remember how it works so you can fix it? Trust me, any non-trivial program that you don't just use once and throw away needs to be written with a careful eye to naming functions and arguments. The ideal is that you should never need to write documentation, because the functions and arguments document themselves. (This is an ideal that never quite works in practice, but we can at least *try*.) An excellent piece of advice I've been given is to write your program's API -- the names of functions, the calling signatures, and so forth -- as if the next person to maintain that code will be a psychopath with a hair-trigger temper and a gun and who knows where you live. Since the next person to maintain it will likely be you, you will save *much* more time in the future by careful and consistent naming than it costs to think of those names right now. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On Sun, Sep 26, 2010 at 3:14 AM, Steven D'Aprano st...@pearwood.info wrote: On Sun, 26 Sep 2010 02:26:25 pm David Hutto wrote: On Sat, Sep 25, 2010 at 9:16 PM, Steven D'Aprano st...@pearwood.info wrote: On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote: Since I had nothing else to do, but practice, this looks much better: def find(word, search): if search in word: print True else: print False [...] OP wanted to find if a in b. Does my function do that?...Yep I didn't say that the function did the wrong thing, I said the name was misleading for what it actually did. Why didn't you call the function len(), or deleteItemsFromPage()? Because those names would be misleading, deceptive and silly. And so is calling a function find() when it does something completely different from the commonly understood meaning of the word find. When you find something, you know where it is afterwards. Find to me, in the since of the OP's question means a hit. It was found in the furtherence into where, is up to the OP and their next question on the list that says now that I know it's there, where is it? In the context of text searches, that means returning an offset to where the target is found, or something similar. That's what str.find() does, and regular expressions, and list.index(). Your find function is a membership test, which is what the `in` operator is for. And I'm sure that with google, and my trust Building Skills in Python Manual at my side, I would have found those string/list functions, and overtime so will the OP, just as did at one point Mr. Miyagi. Yes, we found your terms on the Internet, but we won't tell you where. If you would like to find something else, we won't tell you where that is either. It's not supposed to be a four line version of Google. I didn't say it was. I tried to inject a little humour into the email, but it clearly didn't work. It did work, so I injected a little sarcasm back. [...] Even this is slightly misleading, because text doesn't need to be an actual string. It could be any sequence, such as a list. I know this from a brief exercise I was working on before, but when learning, you can just give everything at once and expect it to be absorbed, you have to practive with the different types you can manipulate, but knowing what they are is helpful. But this gives the *intention* of the function, which is to do text searches. So this is (in my opinion) an acceptable compromise between intention and generality. Semantics, are only important to those who didn't write it. Semantics means meaning. If you are trying to tell me that the meaning of programs -- their *purpose* -- is unimportant, that it doesn't matter what a function does, I'm afraid you'll have your work cut out to convince me. I meant if it's a small function that you might use once in a blue moon, and you know what it does for you, and since you wrote this small function, you're able to tell exactly what it does, and then it does this task as expected for you, then ok. If I was working with someone else on it, then I'm sure, they would suggest, that we use overlapping terminology we could agree on for the code at hand. (it would probably require a meeting or something.) The most important reader of your functions is... you. The function might be fresh in your mind *today*, but tomorrow? Next week? Six months from now when you discover a bug in your program and are trying to remember how it works so you can fix it? It's five lines long. Trust me, any non-trivial program that you don't just use once and throw away needs to be written with a careful eye to naming functions and arguments. The ideal is that you should never need to write documentation, because the functions and arguments document themselves. (This is an ideal that never quite works in practice, but we can at least *try*.) and I do. An excellent piece of advice I've been given is to write your program's API -- the names of functions, the calling signatures, and so forth -- as if the next person to maintain that code will be a psychopath with a hair-trigger temper and a gun and who knows where you live. Since the next person to maintain it will likely be you, you will save *much* more time in the future by careful and consistent naming than it costs to think of those names right now. Your comments are in the suggestion box, and you'll be happy to know, I even take advice from my critics...when it suits me. -- Steven D'Aprano ___ Tutor maillist - tu...@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor David Hutto ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
This returns a if a in, or -1 if using z: class zoeken() : pass def __len__(self): return 0 def __str__(self): return test2 def find(self, strng, ch, start, stop): index = start while index len(strng) and index stop: if strng[index] == ch: return ch index += 1 return -1 test = zoeken() test.woord = tamara stop = len(test.woord) test2 = test.find(test.woord, a, 1,stop) print test2 David ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
This is a little better, it returns a if a in, or None if using z: class zoeken() : pass def __len__(self): return 0 def __str__(self): return test2 def find(self, strng, ch, start, stop): index = start while index len(strng) and index stop: if strng[index] == ch: return ch index += 1 test = zoeken() test.woord = raw_input('Enter string of letters to search: ' ) stop = len(test.woord) search = raw_input('Enter character to find: ') #print 'search =' ,search test2 = test.find(test.woord, search, 1,stop) print test2 Of course, there are other ways to accomplish this. David ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
Since I had nothing else to do, but practice, this looks much better: def find(word, search): if search in word: print True else: print False word = raw_input('Enter string of letters to search: ' ) search = raw_input('Enter character to find: ') find(word,search) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class method problem
On Sun, 26 Sep 2010 04:15:03 am Roelof Wobben wrote: Hello, I have this code: class zoeken() : It is traditional to name classes with an initial capital letter, so Zoeken would be better. pass What is the point of the pass statement there? That does nothing. Why did you put that there? def __len__(self): return 0 def __str__(self): return test2 What is test2? It doesn't exist. def find(self, strng, ch, start, stop): Count the arguments: 5, including self. Remember that number. This is important later on. index = start while index len(strng) and index stop: if strng[index] == ch: return index index += 1 return -1 Watch the indentation. The return -1 is *inside* the loop. test = zoeken() test.woord = tamara test2 = zoeken.find(test, a, 1,5) print test(test2) But now I get this message : Traceback (most recent call last): File C:\Users\wobben\workspace\oefeningen\src\test.py, line 20, in module test2 = zoeken.find(test, a, 1,5) TypeError: find() takes exactly 5 arguments (4 given) Right. READ THE ERROR, don't just immediately cry for help. Being a programmer means you must have ATTENTION TO DETAIL -- the error tells you *exactly* what the problem is: the find() method takes five arguments, *including* self. You have only given four arguments: find method expects: 1: self 2: strng 3: ch 4: start 5: stop find method actually gets 1: test 2: a 3: 1 4: 5 5: ?? I can do zoeken.find (test2,test, a, 1,5) but then I get this message: Traceback (most recent call last): File C:\Users\wobben\workspace\oefeningen\src\test.py, line 20, in module zoeken.find( test2, test, a, 1,5) NameError: name 'test2' is not defined Exactly. That's because test2 does not exist. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor