Re: [Tutor] Wondering about a project

2015-02-03 Thread dw
Well I've made some progress in terminal mode.
The OS is Ubuntu 12.04 LXDE desktop
This script works.
It prompts for the url, lets the user confirm download and then runs the
video in Gnome-Player.  

Once Gnome-Player is dropped by the user, it prompts to either move the
file to storage or delete.  Then returns for another round.
---
#!/usr/bin/python
from subprocess import call
import glob,re,shutil,os,time

geturl=""
while True:
call(["clear"])
geturl= input("Enter Youtube URL ")
if len(geturl)==0:
break

def unquote(geturl):
return re.compile('%([0-9a-fA-F]{2})',re.M).sub(lambda m:
chr(int(m.group(1),16)), geturl)
print("Download %s?" %geturl)
answer= raw_input("Press ENTER to continue: ")
call(["youtube-dl", geturl])

#get the youtube video file names
YTfile=glob.glob('./*.mp4')
print("%s Youtube files: "%(YTfile))

#clean up the file names
for x in range(len(YTfile)):
YTfile[x] = YTfile[x][2:]
print("%s: "+str(x)+" "+YTfile[x]+'\n')

#now play the youtube video
#for x in range(len(YTfile)):
call(["gnome-mplayer", YTfile[0]])

#Decide to save the file or delete it
dofile = raw_input('Save or Delete: S or D ')
if dofile=='S':

#save the file by moving it into folder
for x in range(len(YTfile)):
shutil.move(YTfile[x],'/home/user/Documents/YOUTUBEFILES')  

#delete the file
else:
os.remove(YTfile[0])
print("Deleted %s "%YTfile[0])
time.sleep( 3 )
-- 
 bw...@fastmail.net

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


Re: [Tutor] Wondering about a project

2015-02-03 Thread Alan Gauld

On 02/02/15 18:42, dw wrote:


geturl=""


You don't really need this since you assign it inside the loop.


while True:
 call(["clear"])
 geturl= input("Enter Youtube URL ")
 if len(geturl)==0:
 break

 def unquote(geturl):
 return re.compile('%([0-9a-fA-F]{2})',re.M).sub(lambda m:
 chr(int(m.group(1),16)), geturl)


Its not a good idea to define a functin inside a loop.
Everytime the loop is executed you redefine the function all over again, 
which is a waste. Keep the function definitions out of

your main code.


 print("Download %s?" %geturl)
 answer= raw_input("Press ENTER to continue: ")


If you are using Python2.7 then you should also use
raw_input above to get the url.


 call(["youtube-dl", geturl])

#get the youtube video file names
 YTfile=glob.glob('./*.mp4')
 print("%s Youtube files: "%(YTfile))

#clean up the file names
 for x in range(len(YTfile)):
YTfile[x] = YTfile[x][2:]
 print("%s: "+str(x)+" "+YTfile[x]+'\n')


this would be prettier using enumerate:

for x, file in enumerate(YTFile):
YTFile[x] = file[2:]
print("%s:%d" % (file, x))


#now play the youtube video
 #for x in range(len(YTfile)):


Again this would be prettier using normal python style
for file in YTFile:


 call(["gnome-mplayer", YTfile[0]])

#Decide to save the file or delete it
 dofile = raw_input('Save or Delete: S or D ')
 if dofile=='S':


You will get annoyed always having to press shift key to
get caps. You should check for one case after forcing
conversion:

if dofile.upper() == 'S':


Although after writing a GUI that will be less of an
issue because you'll be using a dialog to get the choice.


#save the file by moving it into folder
 for x in range(len(YTfile)):
 shutil.move(YTfile[x],'/home/user/Documents/YOUTUBEFILES')


Again, don't use indexing, Let python do the work, its more reliable.

for file in YTFile:
shutil.move(file, 'your/path')


#delete the file
 else:
 os.remove(YTfile[0])
 print("Deleted %s "%YTfile[0])
 time.sleep( 3 )


Note that this else will delete the file even if the user presses 's' 
instead of 'S' unless you do the upper conversion I show above.

It will also delete the file if the user happens to hit return
before 's'...
I'd recommend an explicit test for 'D' here.
But again, not an issue in a GUI version.


--
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] Wondering about a project

2015-02-03 Thread Dave Angel

On 02/03/2015 07:12 AM, Alan Gauld wrote:

On 02/02/15 18:42, dw wrote:



You forgot to tell us the Python version you're targeting.  From various 
clues in your code, I have to assume you're using 2.7, but if I'm wrong, 
there are other comments I should have made.



geturl=""


You don't really need this since you assign it inside the loop.


while True:
 call(["clear"])
 geturl= input("Enter Youtube URL ")


Need to use raw_input() for version 2.7.  As it stands, you're requiring 
the user to enter quotes around his response, and taking the risk that 
if he doesn't, or if they're unmatched, he might be doing some 
unexpected things.



 if len(geturl)==0:
 break

 def unquote(geturl):
 return re.compile('%([0-9a-fA-F]{2})',re.M).sub(lambda m:
 chr(int(m.group(1),16)), geturl)


Its not a good idea to define a functin inside a loop.
Everytime the loop is executed you redefine the function all over again,
which is a waste. Keep the function definitions out of
your main code.


 print("Download %s?" %geturl)
 answer= raw_input("Press ENTER to continue: ")


If you are using Python2.7 then you should also use
raw_input above to get the url.


 call(["youtube-dl", geturl])

#get the youtube video file names
 YTfile=glob.glob('./*.mp4')
 print("%s Youtube files: "%(YTfile))

You need to decide here whether there might be more than one file to 
play and/or delete.  If your design says there's just one file, then you 
should ensure that, perhaps by deleting the others before the loop 
below, or by printing an error message.  I'll assume you're designing 
for the possibility of multiple files on that Youtube page.  I don't 
know youtube-dl well enough to know if that's possible.




#clean up the file names
 for x in range(len(YTfile)):
YTfile[x] = YTfile[x][2:]
 print("%s: "+str(x)+" "+YTfile[x]+'\n')


this would be prettier using enumerate:

for x, file in enumerate(YTFile):
 YTFile[x] = file[2:]
 print("%s:%d" % (file, x))


#now play the youtube video


That's now "videos", plural.


 #for x in range(len(YTfile)):


Again this would be prettier using normal python style
for file in YTFile:

for myfile in YTFile:
call(["gnome-mplayer", myfile)

Besides which, if you had uncommented the range thing, you'd need to 
change the [0] below to [x].  Otherwise you'd be playing the first file 
multiple times.





 call(["gnome-mplayer", YTfile[0]])

#Decide to save the file or delete it
 dofile = raw_input('Save or Delete: S or D ')
 if dofile=='S':


Here again, your design has to decide whether it'll be all or nothing. 
I'll assume you'll be either saving them all, or deleting them all.




You will get annoyed always having to press shift key to
get caps. You should check for one case after forcing
conversion:

if dofile.upper() == 'S':


Although after writing a GUI that will be less of an
issue because you'll be using a dialog to get the choice.


#save the file by moving it into folder


save the files by moving them into folder


 for x in range(len(YTfile)):
 shutil.move(YTfile[x],'/home/user/Documents/YOUTUBEFILES')


Again, don't use indexing, Let python do the work, its more reliable.

for file in YTFile:
 shutil.move(file, 'your/path')


#delete the file
 else:
 os.remove(YTfile[0])
 print("Deleted %s "%YTfile[0])
 time.sleep( 3 )


You're only deleting the first one.  Need a loop here as well.


Note that this else will delete the file even if the user presses 's'
instead of 'S' unless you do the upper conversion I show above.
It will also delete the file if the user happens to hit return
before 's'...
I'd recommend an explicit test for 'D' here.
But again, not an issue in a GUI version.





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


[Tutor] Macintosh Help with Python

2015-02-03 Thread Mark Warren
Can you help me through a phone number or chat on working with Python?

-- 
Mark Warren
Humboldt Unified School District # 258
801 New York Street
Humboldt, Kansas  66748
Phone -- (620) 704-1527
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Macintosh Help with Python

2015-02-03 Thread Alan Gauld

On 03/02/15 15:22, Mark Warren wrote:

Can you help me through a phone number or chat on working with Python?


Sorry Mark, this is a mailing list. We can answer questions
posted by email. If you tell us what it is you want to do
somebody can describe the process for you.

There are also a ton of videos on YouTube on using Python
on different platforms.

Here is one for MacOSX:

https://www.youtube.com/watch?feature=player_detailpage&v=BE1wDsLzOJA

But there are many others.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


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


[Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

Hello,

I was writing something and thought: Since the class had some 
'constants', and multiple instances would be created, I assume that each 
instance would have its own data. So this would mean duplication of the 
same constants? If so, I thought why not put the constants in memory 
once, for every instance to access (to reduce memory usage).


Correct me if I'm wrong in my assumptions (i.e: If instances share stuff).

So I investigated further..

>>> import sys
>>> sys.getsizeof(5)
12


So an integer on my machine is 12 bytes.

Now:

>>> class foo(object):
... def __init__(self):
... pass

>>> sys.getsizeof(foo)
448 

>>> sys.getsizeof(foo())
28

>>> foo

>>> foo()
<__main__.foo object at 0xXXX


- Second weird thing:

>>> class bar(object):
... def __init__(self):
... self.w = 5
... self.x = 6
... self.y = 7
... self.z = 8

>>> sys.getsizeof(bar)
448
>>> sys.getsizeof(foo)
448
>>> sys.getsizeof(bar())
28
>>> sys.getsizeof(foo())
28

>>> sys.getsizeof(bar().x)
12
>>> sys.getsizeof(bar().y)
12


Summary questions:

1 - Why are foo's and bar's class sizes the same? (foo's just a nop)
2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?
3 - Why's bar()'s size smaller than the sum of the sizes of 4 integers?



Thanks..

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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Danny Yoo
 class bar(object):
> ... def __init__(self):
> ... self.w = 5
> ... self.x = 6
> ... self.y = 7
> ... self.z = 8
>
 sys.getsizeof(bar())
> 28
> 3 - Why's bar()'s size smaller than the sum of the sizes of 4 integers?


But what is the documented behavior of sys.getsizeof?

Reading...

https://docs.python.org/3/library/sys.html#sys.getsizeof

Ah.  The following phrase in the documentation seems to apply directly
to your question:

"Only the memory consumption directly attributed to the object is
accounted for, not the memory consumption of objects it refers to."

But the docs there also have a link to a recursive getsizeof() recipe
that does what I think you intend.  Take a look at that recipe.


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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Emile van Sebille

On 2/3/2015 1:12 PM, Jugurtha Hadjar wrote:

Hello,

I was writing something and thought: Since the class had some
'constants', and multiple instances would be created, I assume that each
instance would have its own data. So this would mean duplication of the
same constants? If so, I thought why not put the constants in memory
once, for every instance to access (to reduce memory usage).

Correct me if I'm wrong in my assumptions (i.e: If instances share stuff).

So I investigated further..

 >>> import sys
 >>> sys.getsizeof(5)
12


So an integer on my machine is 12 bytes.

Now:

 >>> class foo(object):
...def __init__(self):
...pass

 >>> sys.getsizeof(foo)
448

 >>> sys.getsizeof(foo())
28

 >>> foo

 >>> foo()
<__main__.foo object at 0xXXX


- Second weird thing:

 >>> class bar(object):
...def __init__(self):
...self.w = 5
...self.x = 6
...self.y = 7
...self.z = 8

 >>> sys.getsizeof(bar)
448
 >>> sys.getsizeof(foo)
448
 >>> sys.getsizeof(bar())
28
 >>> sys.getsizeof(foo())
28

 >>> sys.getsizeof(bar().x)
12
 >>> sys.getsizeof(bar().y)
12


Summary questions:

1 - Why are foo's and bar's class sizes the same? (foo's just a nop)


i'm not sure on this one.


2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?


neither foo() nor bar() return anything explicitly, so both return the 
default none




3 - Why's bar()'s size smaller than the sum of the sizes of 4 integers?


same as above.

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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Danny Yoo
>>
>> Summary questions:
>>
>> 1 - Why are foo's and bar's class sizes the same? (foo's just a nop)
>
>
> i'm not sure on this one.
>
>> 2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?
>
>
> neither foo() nor bar() return anything explicitly, so both return the
> default none


This needs correction.  I think you're thinking of regular functions.
But 'foo' and 'bar' are the names of the classes, so this is instance
construction.


To demonstrate the difference:

#
>>> class foo(object): pass
...
>>> foo()
<__main__.foo object at 0x7f27655c0fd0>
#



Compare what we see here to:

##
>>> def bar(): pass
...
>>> bar()
>>>
##

where the interactive evaluator is suppressing output of the None value.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Zachary Ware
On Tue, Feb 3, 2015 at 3:59 PM, Emile van Sebille  wrote:
> On 2/3/2015 1:12 PM, Jugurtha Hadjar wrote:
>> 2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?
>
> neither foo() nor bar() return anything explicitly, so both return the
> default none

This is not correct, foo() and bar() return a foo instance and a bar
instance, respectively; not None.

For the OP: while this will probably be a nice exercise for learning
more about Python's internals, please keep in mind that 9 times out of
10 you won't need to worry about memory usage in Python, especially
not before you've proven to yourself that your program is using more
memory than is acceptable.

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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Peter Otten
Jugurtha Hadjar wrote:

> Hello,
> 
> I was writing something and thought: Since the class had some
> 'constants', and multiple instances would be created, I assume that each
> instance would have its own data. So this would mean duplication of the
> same constants? If so, I thought why not put the constants in memory
> once, for every instance to access (to reduce memory usage).

CPython already does this for many common values, e. g. small integers and 
variable names


>>> a = 42
>>> b = 42
>>> a is b
True
>>> a = 300
>>> b = 300
>>> a is b
False

It also performs constant folding over a single compilation:

>>> a = 300; b = 300; a is b
True

> Correct me if I'm wrong in my assumptions (i.e: If instances share stuff).
> 
> So I investigated further..
> 
>  >>> import sys
>  >>> sys.getsizeof(5)
> 12
> 
> 
> So an integer on my machine is 12 bytes.
> 
> Now:
> 
>  >>> class foo(object):
> ...   def __init__(self):
> ...   pass
> 
>  >>> sys.getsizeof(foo)
> 448
> 
>  >>> sys.getsizeof(foo())
> 28
> 
>  >>> foo
> 
>  >>> foo()
> <__main__.foo object at 0xXXX

To know its class the foo instance only needs a reference to the class 
object, not a complete copy of the class. This is typically provided by 
putting a pointer into the instance, and this consumes only 8 bytes on 64-
bit systems.


> - Second weird thing:
> 
>  >>> class bar(object):
> ...   def __init__(self):
> ...   self.w = 5
> ...   self.x = 6
> ...   self.y = 7
> ...   self.z = 8
> 
>  >>> sys.getsizeof(bar)
> 448
>  >>> sys.getsizeof(foo)
> 448
>  >>> sys.getsizeof(bar())
> 28
>  >>> sys.getsizeof(foo())
> 28
> 
>  >>> sys.getsizeof(bar().x)
> 12
>  >>> sys.getsizeof(bar().y)
> 12

The instances of most user-defined classes use a dict to hold references to 
the attributes, and only the memory consumed by the pointer to that dict is 
reported. If all referenced values were included, what would you expect to 
be the size of `a` below

>>> class A: pass
... 
>>> a = A()
>>> a.a = a
>>> sys.getsizeof(a)
56


> Summary questions:
> 
> 1 - Why are foo's and bar's class sizes the same? (foo's just a nop)

Assigning attributes in the initializer only affects the instance; Python 
doesn't scan the code to reserve slots for these attributes. When the 
instance is created the initialiser is executed and every

self.x = value

basically results in 

self.__dict__["x"] = value

> 2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?

To get a more realistic idea of the objects' size you can include the size 
of __dict__. That grows in bursts:

>>> class A: pass
... 
>>> a = A()
>>> old_size = sys.getsizeof(a.__dict__)
>>> for i in range(1000):
... setattr(a, "x" + str(i), i)
... new_size = sys.getsizeof(a.__dict__)
... if new_size != old_size:
... print(i, "a.__dict__ grows from", old_size, "to", new_size)
... old_size = new_size
... 
3 a.__dict__ grows from 96 to 192
11 a.__dict__ grows from 192 to 320
21 a.__dict__ grows from 320 to 576
43 a.__dict__ grows from 576 to 1088
85 a.__dict__ grows from 1088 to 2112
171 a.__dict__ grows from 2112 to 4160
341 a.__dict__ grows from 4160 to 8256
683 a.__dict__ grows from 8256 to 16448

> 3 - Why's bar()'s size smaller than the sum of the sizes of 4 integers?

>From the above follows that this is not a meaningful question for a standard 
user-defined class. They all use __dict__ to store the interesting stuff.

But there is a way to reserve space for attributes in the instance:

>>> class A:
... __slots__ = ()
... 
>>> class B:
... __slots__ = ("a",)
... 
>>> class C:
... __slots__ = ("a", "b")
... 
>>> class D:
... __slots__ = tuple("a" + str(i) for i in range(100))
... 
>>> for K in A, B, C, D:
... print(K.__name__, sys.getsizeof(K()))
... 
A 16
B 48
C 56
D 840
>>> b = B()
>>> sys.getsizeof(b)
48
>>> b.a = 42
>>> sys.getsizeof(b)
48

>>> (840-48)/99
8.0

And that looks very much like one 64-bit pointer per attribute.


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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

On 02/03/2015 10:57 PM, Danny Yoo wrote:


But what is the documented behavior of sys.getsizeof?

Reading...

 https://docs.python.org/3/library/sys.html#sys.getsizeof



Ah !

I was reading this:

https://docs.python.org/2/library/sys.html#sys.getsizeof


The unlocking phrase:


"Only the memory consumption directly attributed to the object is
accounted for, not the memory consumption of objects it refers to."



seems to be present in the Python 3 doc, but not in Python 2's. I'll 
make sure to include the version in my future questions.




But the docs there also have a link to a recursive getsizeof() recipe
that does what I think you intend.  Take a look at that recipe.


Good luck!



Yeap, I see that. Thanks for your time!

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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

On 02/03/2015 11:28 PM, Zachary Ware wrote:


For the OP: while this will probably be a nice exercise for learning
more about Python's internals, please keep in mind that 9 times out of
10 you won't need to worry about memory usage in Python, especially
not before you've proven to yourself that your program is using more
memory than is acceptable.



Thanks for the pointer, I was scratching the itch on my way to do 
something else... But this stuff is fascinating and hard to resist!



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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Steven D'Aprano
On Tue, Feb 03, 2015 at 10:12:09PM +0100, Jugurtha Hadjar wrote:
> Hello,
> 
> I was writing something and thought: Since the class had some 
> 'constants', and multiple instances would be created, I assume that each 
> instance would have its own data. So this would mean duplication of the 
> same constants?

Not necessarily. Consider:

class A(object):
spam = 23
def __init__(self):
self.eggs = 42

In this case, the "spam" attribute is on the class, not the instance, 
and so it doesn't matter how many A instances you have, there is only 
one reference to 23 and a single copy of 23.

The "eggs" attribute is on the instance. That means that each instance 
has its own separate reference to 42. 

Does that mean a separate copy of 42? Maybe, maybe not. In general, yes: 
if eggs was a mutable object like a list, or a dict, say:

self.eggs = []

then naturally it would need to be a separate list for each instance. 
(If you wanted a single list shared between all instances, put it on the 
class.) But with immutable objects like ints, strings and floats, there 
is an optimization available to the Python compiler: it could reuse the 
same object. There would be a separate reference to that object per 
instance, but only one copy of the object itself.

Think of references as being rather like C pointers. References are 
cheap, while objects themselves could be arbitrarily large.

With current versions of Python, the compiler will intern and re-use 
small integers and strings which look like identifiers ("alpha" is an 
identifier, "hello world!" is not). But that is subject to change: it is 
not a language promise, it is an implementation optimization.

However, starting with (I think) Python 3.4 or 3.5, Python will optimize 
even more! Instances will share dictionaries, which will save even more 
memory. Each instance has a dict, which points to a hash table of (key, 
value) records:


 __dict__ > [ UNUSED UNUSED (ptr to key, ptr to value) UNUSED ... ]


 __dict__ > [ UNUSED UNUSED (ptr to key, ptr to value) UNUSED ... ]

For most classes, the instances a and b will have the same set of keys, 
even though the values will be different. That means the pointers to 
keys are all the same. So the new implementation of dict will optimize 
that case to save memory and speed up dictionary access.


> If so, I thought why not put the constants in memory 
> once, for every instance to access (to reduce memory usage).
> 
> Correct me if I'm wrong in my assumptions (i.e: If instances share stuff).

In general, Python will share stuff if it can, although maybe not 
*everything* it can.


> So I investigated further..
> 
> >>> import sys
> >>> sys.getsizeof(5)
> 12
> 
> 
> So an integer on my machine is 12 bytes.

A *small* integer is 12 bytes. A large integer can be more:

py> sys.getsizeof(2**100)
26
py> sys.getsizeof(2**1)
1346
py> sys.getsizeof(2**1000)
146


> Now:
> 
> >>> class foo(object):
> ...   def __init__(self):
> ...   pass
> 
> >>> sys.getsizeof(foo)
> 448   
> 
> >>> sys.getsizeof(foo())
> 28
> 
> >>> foo
> 
> >>> foo()
> <__main__.foo object at 0xXXX

The *class* Foo is a fairly large object. It has space for a name, a 
dictionary of methods and attributes, a tuple of base classes, a 
table of weak references, a docstring, and more:

py> class Foo(object):
... pass
...
py> dir(Foo)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', 
'__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', 
'__qualname__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'__weakref__']
py> vars(Foo)
mappingproxy({'__qualname__': 'Foo', '__module__': '__main__', 
'__doc__': None, '__weakref__': , '__dict__': })
py> Foo.__base__

py> Foo.__bases__
(,)

The instance may be quite small, but of course that depends on how many 
attributes it has. Typically, all the methods live in the class, and are 
shared, while data attributes are per-instance.


> - Second weird thing:
> 
> >>> class bar(object):
> ...   def __init__(self):
> ...   self.w = 5
> ...   self.x = 6
> ...   self.y = 7
> ...   self.z = 8
> 
> >>> sys.getsizeof(bar)
> 448
> >>> sys.getsizeof(foo)
> 448

Nothing weird here. Both your Foo and Bar classes contain the same 
attributes. The only difference is that Foo.__init__ method does 
nothing, while Bar.__init__ has some code in it.

If you call

sys.getsizeof(foo.__init__.__code__)

and compare it to the same for bar, you should see a difference.


> >>> sys.getsizeof(bar())
> 28
> >>> sys.getsizeof(foo())
> 28

In this case, the Foo and Bar instances both have the same size. They 
both have a __dict__, and the Foo instance's __dict__ is empty, while 
the Bar instance's __dict__ has 4 items. Print:

print(foo().__dict__)
print(bar().__dict__)

to see the difference. But w

Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Dave Angel

On 02/03/2015 04:12 PM, Jugurtha Hadjar wrote:

Hello,



Lots of other good comments, so I'll just remark on one point.



 >>> class bar(object):
...def __init__(self):
...self.w = 5
...self.x = 6
...self.y = 7
...self.z = 8



If these really are "constants," meaning the same value for all 
instances, then you can make them class attributes instead of instance 
attributes.  I'd advise doing this to avoid bugs, not to save memory, 
though if you have lots of instances, it'll certainly save memory.


>>> class bar(object):
...w = 5
...x = 6
...def __init__(self):
...self.y = 7
...self.z = 8

At this point, all instances will have a self.w of 5, and a self.x of 6. 
 But they'll each have a self.y and self.z which could change 
independently.




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


Re: [Tutor] Wondering about a project

2015-02-03 Thread dw
Thanks Alan for the tips!!!
I greatly appreciate.  :-D
Duane
-- 
 bw...@fastmail.net

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


Re: [Tutor] Wondering about a project

2015-02-03 Thread dw
Thanks Dave A for your Tips!!
I greatly appreciate.  :-D
Duane
-- 
 bw...@fastmail.net

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


[Tutor] How can I replicate a list in a for loop

2015-02-03 Thread Suresh Nagulavancha
This is my sample piece of code (not full code of my original code just sample 
of it)
I am using python 2.7
Import itertools
var=[1,2,3,4,5]
Length=int(raw_input("length of possible numbers required"))
#This is for length of 3 chars
for i in itertools.product(var,var,var):
  print i[0]+i[1]+i[2]


Here what is my problem is i am unable to replicate the list based on the user 
input i tried var*length but it is creating a new single list with repeated 
values , how can i solve this problem?? I want the same original list to be used


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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

On 02/03/2015 11:40 PM, Peter Otten wrote:


CPython already does this for many common values, e. g. small integers and
variable names



a = 42
b = 42
a is b

True

a = 300
b = 300
a is b

False



The threshold seems to be 256 (last value where it evaluates to True):

>>> a = 1
>>> b = 1
>>> same = True
>>> while same:
... a += 1
... b += 1
... same = a is b
...
>>> a
257
>>> b
257

Interesting that it does that, and interesting that it doesn't work for 
floats.




To know its class the foo instance only needs a reference to the class
object, not a complete copy of the class. This is typically provided by
putting a pointer into the instance, and this consumes only 8 bytes on 64-
bit systems.


Okay, I thought the way it was done was that each instance was a full, 
independent, citizen/entity; with everything copied as many times as 
there are instances, which somehow bothered me memory wise, but had an 
appeal of having them completely separated.



...


Rest of the post is partially grasped and requires further reading to 
fully appreciate. Thank you very much for taking the time and for the 
example code.




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


Re: [Tutor] How can I replicate a list in a for loop

2015-02-03 Thread Mark Lawrence

On 03/02/2015 22:51, Suresh Nagulavancha wrote:

This is my sample piece of code (not full code of my original code just sample 
of it)
I am using python 2.7
Import itertools
var=[1,2,3,4,5]
Length=int(raw_input("length of possible numbers required"))
#This is for length of 3 chars
for i in itertools.product(var,var,var):
   print i[0]+i[1]+i[2]

Here what is my problem is i am unable to replicate the list based on the user 
input i tried var*length but it is creating a new single list with repeated 
values , how can i solve this problem?? I want the same original list to be used

Thanks in advance


If you are trying to get the first n items from the list all you need is 
the slice notation:-


chunk = var[:Length]

If not can you please rephrase your question as it makes no sense to me.

--
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

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


Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

On 02/04/2015 12:18 AM, Steven D'Aprano wrote:



Not necessarily. Consider:

class A(object):
 spam = 23
 def __init__(self):
 self.eggs = 42

In this case, the "spam" attribute is on the class, not the instance,
and so it doesn't matter how many A instances you have, there is only
one reference to 23 and a single copy of 23.

The "eggs" attribute is on the instance. That means that each instance
has its own separate reference to 42.




Hmm.. Here are the first few lines of my class:

class Sender(object):
"""
Redacted
"""

SENDER_DB = 'sender.db'

def __init__(self, phone, balance=0.0):
self.phone = phone
self.balance = balance

I gave the (bad) examples that way because I thought what mattered is 
how much data was inside. I put SENDER_DB there because it made sense to 
put constants way on top, not because I had any idea it'd make the 
difference you mentioned (class attributes vs instance attributes).


And also because it's a common piece of data to all the 
methods...(because after I started with each method opening and closing 
the database,
I eliminated the code and made a method that returns a connection and a 
cursor, and the others just call it when they need to do stuff on the 
database. I'll ask another question later on how to refine it)


But now that you, Dave, and Peter pointed this out, I'm thinking of 
putting the methods' constants up there (mainly patterns for regular 
expressions, and queries (SQL)).




Does that mean a separate copy of 42? Maybe, maybe not. In general, yes:
if eggs was a mutable object like a list, or a dict, say:

 self.eggs = []

then naturally it would need to be a separate list for each instance.
(If you wanted a single list shared between all instances, put it on the
class.) But with immutable objects like ints, strings and floats, there
is an optimization available to the Python compiler: it could reuse the
same object. There would be a separate reference to that object per
instance, but only one copy of the object itself.


Okay.. I think that even if Python does optimize that, this belongs to 
the "good practice" category, so it's better that I'm the one who does 
it instead of relying on what the compiler might do. I'm a 
beginner(that's the first thing I write that does something useful) and 
would like to reinforce good habits.




Think of references as being rather like C pointers. References are
cheap, while objects themselves could be arbitrarily large.



That's the analogy I made, but I'm careful with those. I don't want to 
end up like the "English As She Is Spoke" book..




With current versions of Python, the compiler will intern and re-use
small integers and strings which look like identifiers ("alpha" is an
identifier, "hello world!" is not).



...



In general, Python will share stuff if it can, although maybe not
*everything* it can.


That's interesting. I'll try to read up on this without being sidetracked.




In this case, the Foo and Bar instances both have the same size. They
both have a __dict__, and the Foo instance's __dict__ is empty, while
the Bar instance's __dict__ has 4 items. Print:

print(foo().__dict__)
print(bar().__dict__)

to see the difference. But with only 4 items, Bar's items will fit in
the default sized hash table. No resize will be triggered and the sizes
are the same.


I thought that there was a default size allocated even for an "empty" 
class (which is correct), and then if I added w, x, y, z, their size 
would be *added* to the default size (which is incorrect)..


Somehow, I didn't think of the analogy of 8dec being (1000b) (4 bits) 
and incrementing, it's still 4 bits through 15dec (b).


So that's: default class size + data = default class size until it 
"overflows".  (or until 50% of default class size is reached as you 
mentioned later).



Run this little snippet of code to see what happens:
d = {}
for c in "abcdefghijklm":
 print(len(d), sys.getsizeof(d))
 d[c] = None


For memo:

(0, 136)
(1, 136)
(2, 136)
(3, 136)
(4, 136)
(5, 136)
(6, 520)
(7, 520)
(8, 520)
(9, 520)
(10, 520)
(11, 520)
(12, 520)


Summary questions:

1 - Why are foo's and bar's class sizes the same? (foo's just a nop)


Foo is a class, it certainly isn't a NOP. Just because you haven't given
it state or behaviour doesn't mean it doesn't have any. It has the
default state and behaviour that all classes start off with.


2 - Why are foo() and bar() the same size, even with bar()'s 4 integers?


Because hash tables (dicts) contain empty slots. Once the hash table
reaches 50% full, a resize is triggered.


3 - Why's bar()'s size smaller than the sum of the sizes of 4 integers?


Because sys.getsizeof tells you the size of the object, not the objects
referred to by the object. Here is a recipe for a recursive getsizeof:

http://code.activestate.com/recipes/577504




This is cool. Thanks a lot (and Dave, too) for the gr

Re: [Tutor] Why is an instance smaller than the sum of its components?

2015-02-03 Thread Jugurtha Hadjar

Sorry for the full lines. They were wrapped here but were sent unfolded.
It seems I need to "rewrap" on Thunderbird.

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