Re: [Tutor] class functions/staticmethod?

2019-08-13 Thread Cameron Simpson

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?

2019-08-13 Thread Steven D'Aprano
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?

2019-08-13 Thread Cameron Simpson

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?

2019-08-12 Thread Steven D'Aprano
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?

2019-08-12 Thread Peter Otten
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

2017-07-23 Thread Michael C
thanks!

On Sun, Jul 23, 2017 at 5:35 PM, Danny Yoo  wrote:

> 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

2017-07-23 Thread Mats Wichmann
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

2017-07-23 Thread Danny Yoo
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

2017-07-23 Thread Michael C
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 C 
wrote:

> 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

2017-06-21 Thread Alan Gauld via Tutor
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

2017-02-21 Thread Peter Otten
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

2017-02-21 Thread Alan Gauld via Tutor
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

2017-02-21 Thread Alan Gauld via Tutor
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

2015-01-23 Thread Alan Gauld

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

2015-01-23 Thread Patrick Thunstrom
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

2015-01-23 Thread Danny Yoo
 #@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

2015-01-23 Thread Danny Yoo
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

2015-01-23 Thread Danny Yoo
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

2015-01-22 Thread Danny Yoo
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

2015-01-22 Thread Cameron Simpson

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

2014-05-25 Thread R. Alan Monroe
 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

2014-05-25 Thread Alex Kleider

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

2014-05-25 Thread Alan Gauld

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

2014-05-25 Thread Danny Yoo
 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

2014-02-24 Thread Peter Otten
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

2014-02-24 Thread Sangeeth Saravanaraj
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

2014-02-24 Thread Peter Otten
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

2014-02-24 Thread spir

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

2014-02-24 Thread Sangeeth Saravanaraj
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

2013-12-21 Thread eryksun
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]

2013-12-21 Thread Steven D'Aprano
(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

2013-12-21 Thread Steven D'Aprano
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

2013-12-21 Thread eryksun
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

2013-12-20 Thread Dominik George
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

2013-12-20 Thread Alan Gauld

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

2013-12-20 Thread eryksun
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

2013-12-20 Thread Steven D'Aprano
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

2013-11-17 Thread Reuben
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

2013-11-16 Thread Dominik George
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

2013-11-16 Thread Alan Gauld

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

2013-10-06 Thread Mark Lawrence

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

2013-10-06 Thread Albert-Jan Roskam
- 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

2013-10-05 Thread Albert-Jan Roskam
___

 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

2013-10-05 Thread Alan Gauld

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

2013-10-05 Thread Steven D'Aprano
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

2013-10-05 Thread Steven D'Aprano
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

2013-09-12 Thread Felix Dietrich
 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

2013-09-12 Thread zubair alam
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

2013-09-12 Thread Alan Gauld

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

2013-09-12 Thread Dave Angel
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

2013-09-11 Thread Marc Tompkins
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

2013-02-18 Thread Oscar Benjamin
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

2013-02-18 Thread Peter Otten
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

2012-09-11 Thread Brannon, Terrence


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

2012-02-15 Thread Alan Gauld

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

2012-02-15 Thread Hugo Arts
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

2012-02-15 Thread Sivaram Neelakantan
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

2012-02-15 Thread Mark Lawrence

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

2012-02-15 Thread Mark Lawrence

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

2012-02-06 Thread Dave Angel

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

2012-02-06 Thread Steven D'Aprano
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

2012-01-18 Thread Alan Gauld

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

2012-01-17 Thread Stayvoid
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

2012-01-17 Thread Dave Angel

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

2012-01-01 Thread Hugo Arts
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

2012-01-01 Thread Stayvoid
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

2011-06-27 Thread Alan Gauld

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

2011-06-26 Thread Marc Tompkins
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

2011-06-22 Thread Alan Gauld
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

2011-06-22 Thread Alexandre Conrad
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

2011-06-22 Thread michael scott
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

2011-06-22 Thread Alan Gauld


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

2011-06-22 Thread Alan Gauld


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

2011-01-26 Thread Alan Gauld


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

2011-01-26 Thread Karim


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

2011-01-26 Thread Karim


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

2011-01-26 Thread Elwin Estle
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

2011-01-26 Thread Tino Dai


 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

2011-01-26 Thread Izz ad-Din Ruhulessin
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

2011-01-26 Thread Alan Gauld


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

2011-01-26 Thread Alan Gauld


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

2011-01-26 Thread Elwin Estle

--- 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?

2011-01-26 Thread Emile van Sebille

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?

2011-01-26 Thread Tim Johnson
* 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

2011-01-25 Thread Corey Richardson
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

2011-01-25 Thread Marc Tompkins
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

2011-01-25 Thread Alan Gauld
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

2011-01-25 Thread Karim


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

2011-01-25 Thread Steven D'Aprano

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

2011-01-25 Thread Steven D'Aprano

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

2011-01-25 Thread Corey Richardson
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

2010-09-27 Thread Roelof Wobben


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

2010-09-27 Thread Dave Angel

 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

2010-09-27 Thread Joel Goldstick
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

2010-09-26 Thread Steven D'Aprano
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

2010-09-26 Thread David Hutto
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

2010-09-25 Thread David Hutto
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

2010-09-25 Thread David Hutto
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

2010-09-25 Thread David Hutto
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

2010-09-25 Thread Steven D'Aprano
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


  1   2   3   4   >