[Tutor] could somebody please explain...

2014-09-30 Thread Clayton Kirkwood
I don't understand the multiplicity of some tools. Namely, why is there a
'a+b', operator.add(a,b), operator.__add__(a,b), operator.iadd(a,b),
operator.__iadd__(a,b) and their related operators?

 

Also, I found something that I can't get my mind around. It is part of the
time/date protocols. I've not seen it anywhere else. 

Datetime(year=blah, blah, blah).date/time()

 

datetime(2013,3,6).date() #returns.

datetime.date(2013,3,6)

 

datetime(2013,3,6).time() #returns.

datetime.time(0,0)

 

This is one of the weirder things I've run across. Is this allowed/needed in
other functions/classes, or is it a datetime thing only?

 

Please spare my mind:<))

 

Clayton

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] python code error

2014-09-30 Thread Vignesh Sathiamoorthy
You will find the answer here - 

http://stackoverflow.com/questions/625083/python-init-and-self-what-do-they-do


On Sep 29, 2014, at 4:34 PM, Danny Yoo  wrote:

> On Sun, Sep 28, 2014 at 8:26 AM, Madeleine Austen
>  wrote:
>> Hi
>> 
>> Here is my code:
>> 
>> 
>> from datetime import datetime
>> timeStart = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
>> numberPlates = 0
>> print("There has been {0} number plates since {1}".format (numberPlates,
>> timeStart))
>> 
>> speedLimit = 25
>> distance = 1
>> 
>> class NumberPlates:
>>  """A class that holds information from sensor for ANPR system"""
>>  distance = 1
>> def __init__(self, name, enter, exit):
>> self.number = name
>> self.enter = enter
>> self.exit = exit
>> def speed(self):
>>distance = 1
>>time = exit - enter
>>speed = distance/time
>>print(speed)
>> 
>> 
>> one = NumberPlates("lemon", 1030, 1050)
>> 
>> 
>> one.speed()
>> 
>> 
>> 
>> 
>> It says there are no arguements
> 
> Hi Madeleine,
> 
> 
> Unlike English class, you're not penalized for copying-and-pasting
> errors for diagnostic, bug tracking purposes.  I can tell that you've
> paraphrased the error in some way because what you report has a
> spelling mistake that's not present anywhere in the Python source
> tree.
> 
> What you've done is somewhat akin to what happened to the poor Ecce
> Homo painting:
> 
> http://en.wikipedia.org/wiki/Ecce_Homo_(El%C3%ADas_Garc%C3%ADa_Mart%C3%ADnez)
> 
> in paraphrasing a perfectly good error message.  :P
> 
> 
> Please include the exact error message.  When you do so,
> copy-and-paste is your friend.  When you see the error message, please
> copy and paste the exact error text.  It helps to copy the entire
> error context if it's not too large.  Show the program run.
> 
> 
> Provide more precise information, and that will help folks here give
> you good help.  Good luck!
> ___
> 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] could somebody please explain...

2014-09-30 Thread Alan Gauld

On 30/09/14 23:54, Clayton Kirkwood wrote:

I don't understand the multiplicity of some tools. Namely, why is there a
'a+b', operator.add(a,b), operator.__add__(a,b), operator.iadd(a,b),
operator.__iadd__(a,b) and their related operators?


The operator module is there largely to allow you to pass
operations to functions that take functions as parameters.
For example map() which applies a function to a collection.

total = map(operator.add, [1,2,3,4,5,6])

is the same result as

total = sum([1,2,3,4,5,6])

You could do the same thing with a lambda:

total = map(lambda a,b: a+b, [1,2,3,4,5,6])

But using operator.add makes it easier to read
(and less error prone).

The operator module has functions representing most
of the builtin operations in Python.

I'm not really sure why it implements the dunder methods
(eg operatotor.__add__()) corresponding to the operations though.
I'm sure somebody else can provide a good explanation...


Also, I found something that I can't get my mind around. It is part of the
time/date protocols. I've not seen it anywhere else.

Datetime(year=blah, blah, blah).date/time()


A Datetime object is an instance of a combined date and time.
the date and time  methods return just the date or time parts
of that combined object.


This is one of the weirder things I've run across. Is this allowed/needed in
other functions/classes, or is it a datetime thing only?


The nearest I can think of elsewhere is the complex number
case where you can get the real/imaginary values from a
complex number

>>> n = (1+6j)
>>> n.imag
6.0
>>> n.real
1.0

But similar concepts apply in most classes where attributes,
methods or properties are used to return significant
aspects of the object. An Address might have methods to
return the city or street or house number for example.

--
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] could somebody please explain...

2014-09-30 Thread Steven D'Aprano
On Tue, Sep 30, 2014 at 03:54:42PM -0700, Clayton Kirkwood wrote:

> I don't understand the multiplicity of some tools. Namely, why is there a
> 'a+b', operator.add(a,b), operator.__add__(a,b), operator.iadd(a,b),
> operator.__iadd__(a,b) and their related operators?

The + operator is the public interface, but the implementation that 
makes + work are the special methods __add__ and __radd__ .

When you write in your code:

result = a + b

how does Python know what to do with a and b? In principle, Python could 
hard-code into the language a handful of types that the interpreter 
knows how to add: int, float, str, list, etc. But that is not easily 
extended when a new type is supported, and Python supports "operator 
overloading" where any custom class can define "a + b" to do whatever 
the class developer wants.

So when the Python interpreter executes a + b, when it does is look for 
a special "dunder" (Double UNDERscore) method on a, __add__, or a 
special dunder method __radd__ ("right add") on b, and calls that.

Actually the rules are a bit more complicated than that, which I'm happy 
to explain if you would like, but for simplicity let's ignore __radd__ 
and just say that when Python sees "a + b" what actually gets called is 
a.__add__(b).

So when you create a new class and want it to support the + operator, 
you write a __add__ method:

class Spam:
def __add__(self, other):
...


and now Python knows how to add your Spam instances together.

Sometimes it is useful to treat the + operator as a function, e.g. so 
that you can pass it to another function like reduce. But operators 
aren't values, you can't pass them to functions. This doesn't work:

py> reduce(+, [1, 2, 3, 4])
  File "", line 1
reduce(+, [1, 2, 3, 4])
^
SyntaxError: invalid syntax


But you can wrap the operator in a function using lambda:

py> reduce(lambda a, b: a+b, [1, 2, 3, 4])
10


but a more efficient way is to use the pre-made functions in the 
operator module:

py> import operator
py> reduce(operator.add, [1, 2, 3, 4])
10


So for every operator + - * / ** etc. there is a corresponding function 
version in the operator module, add(), sub() etc.


[ Aside: you might not know about reduce(). It takes a function f, and a 
list [a, b, c, d, ...] and calls the function with the first two values:

result = f(a, b)

then takes that result and repeatedly calls the function again with the 
next value from the list:

result = f(result, c)
result = f(result, d)
...

until there are no more values left, then returns the final result. 
These days, now that Python has a sum() function, reduce() doesn't get 
used very often. ]

So for each operator that Python knows about, there is the operator 
itself, a function version, and one or two special dunder methods:

  OperatorFunctionDunder methods
  ==  ==  =
  +   operator.add__add__  __radd__
  -   operator.sub__sub__  __rsub__
  *   operator.mul__mul__  __rmul__
  **  operator.pow__pow__  __rpow__
  ==  operator.eq __eq__
  !=  operator.ne __ne__

etc.

Then there are the special "augmented assignment" operators, so that 
Python can support writing:

  x += 1
  y -= x

etc. Again, the syntax used is a combined operator-assignment += and 
that ends up calling a special dunder method, __iadd__. And again, there 
are special function versions in the operator module.


In summary:

(1) When you want to add two values, use a + b.

(2) When you want a function that adds two values, use operator.add.

(3) When you want to write a class that supports addition, give it 
the two special dunder methods __add__ and __radd__.

(4) You almost never should call __add__ yourself.



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] could somebody please explain...

2014-09-30 Thread Steven D'Aprano
On Wed, Oct 01, 2014 at 01:58:16AM +0100, Alan Gauld wrote:
> On 30/09/14 23:54, Clayton Kirkwood wrote:
> >I don't understand the multiplicity of some tools. Namely, why is there a
> >'a+b', operator.add(a,b), operator.__add__(a,b), operator.iadd(a,b),
> >operator.__iadd__(a,b) and their related operators?
> 
> The operator module is there largely to allow you to pass
> operations to functions that take functions as parameters.
> For example map() which applies a function to a collection.
> 
> total = map(operator.add, [1,2,3,4,5,6])
> 
> is the same result as
> 
> total = sum([1,2,3,4,5,6])

No, you're thinking of reduce(), not map().

reduce() takes a function and applies it all of the items, pairwise, 
gradually reducing the result down to a single value. map() takes a 
function and applies it to each of the items individually, returning a 
new list.


[...]
> The operator module has functions representing most
> of the builtin operations in Python.
> 
> I'm not really sure why it implements the dunder methods
> (eg operatotor.__add__()) corresponding to the operations though.
> I'm sure somebody else can provide a good explanation...

They're just aliases. According to the documentation, the "official" 
versions are operator.__add__, etc. with the underscore-less versions 
just given for convenience. But in practice everybody uses the 
non-underscore versions.

My advice is to ignore the operator.__add__ and similar 
double-underscore versions. They're longer to type, don't add any 
additional value, and in fact are actually misleading since they don't 
directly call the dunder methods.



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] could somebody please explain...

2014-09-30 Thread Steven D'Aprano
On Tue, Sep 30, 2014 at 03:54:42PM -0700, Clayton Kirkwood wrote:

> Also, I found something that I can't get my mind around. It is part of the
> time/date protocols. I've not seen it anywhere else. 
> 
> Datetime(year=blah, blah, blah).date/time()
> 
> datetime(2013,3,6).date() #returns.
> datetime.date(2013,3,6)
> 
> datetime(2013,3,6).time() #returns.
> datetime.time(0,0)
> 
> This is one of the weirder things I've run across. Is this allowed/needed in
> other functions/classes, or is it a datetime thing only?

I'm afraid I have no clue what part of this you consider weird. Is it 
that the date() and time() methods don't take an argument? That's quite 
common:

py> "Hello".upper()
'Hello'


Or is it that the result of calling date() or time() methods isn't the 
same type of thing as what you started with? Again, that's very common:

py> {1: 'a', 2: 'b'}.keys()  # Start with a dict, returns a list.
[1, 2]


Start with a datetime object. The date() method returns the date part 
alone, so it returns a date object. The time() method returns the time 
part alone, so it returns a time object. 

Or maybe you're weirded out by the leading "datetime" in the name. 
That's unfortunate, but not weird. The datetime module contains at least 
three classes. When you print the class, they show the module name. It 
is unfortunate that the module name happens to have the same name as one 
of those classes:

py> datetime

py> datetime.date

py> datetime.time

py> datetime.datetime



So when you see something like this:

py> d = datetime.datetime(2000, 5, 22, 11, 5, 27)
py> d
datetime.datetime(2000, 5, 22, 11, 5, 27)

the "datetime." means the module, and the "datetime(...)" means the 
class with its various arguments.

Is this common? Sadly, there are quite a few modules where the main 
function or class in the module has the same, or very similar, name:

dis.dis
bisect.bisect
decimal.Decimal
fractions.Fraction

etc.


(P.S. it is better to raise each independent question in a separate 
email.)



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor