Re: [Tutor] Why is an OrderedDict not sliceable?

2016-01-22 Thread Mark Lawrence

On 20/01/2016 13:33, Albert-Jan Roskam wrote:

Hi,

Like the subject says: Why is an OrderedDict not sliceable? (From the 
collections library). Was that an intentional omission, or a mistake? [1]


Plenty of answers on this all ready, but...



Background: I do not use OrderedDict very often, but I thought I could use it 
to look up street and city names using postcodes ([0-9]{4} [a-z]{2} format). I 
needed it to be ordered because I also wanted to be able to use bisect, which 
is needed when the postcode letters are missing. In short: a fast dict lookup 
for complete postcodes and less fast bisect lookup for in complete postcodes.



You appear to be confusing ordered and sorted.  There is no way that you 
can use bisect on an OrderedDict unless it is sorted in the first place.



[1] http://stackoverflow.com/questions/30975339/slicing-a-python-ordereddict

Thanks!

Albert-Jan



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


[Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB

2016-01-22 Thread Arjun Srivatsa
Hello everyone,

I have been trying to insert data (a 'hello world' string) from PLC into
MongoDB using Python API (which pulls the data from PLC and pushes it into
MongoDB). I have been getting the error message '*line 222, in meth  return
getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be
made because the target machine actively refused it*' despite having mongod
running in the Services background for the code I have written below. Also,
the server IP address on which MongoDB is present is 10.52.124.186 and
address of PLC (which I am using it on my PC) is 10.52.124.135. I am have
tried almost everything to sort it out and yet I haven't got a clue as to
how to get past it. Where am I going wrong?







#!/usr/bin/python


import socket

import socket

import pymongo

from pymongo import MongoClient

import datetime


# Connection to server (PLC) on port 27017

server = socket.socket()

host = '10.52.124.135'

port = 27017


server.connect((host, port))

print server.recv(1024)


server.close


#Connection to Client (Mongodb) on port 27017

IP = '10.52.124.186'

PORT = 27017

BUFFER_SIZE = 1024


client = MongoClient('10.52.124.186', 27017)

db = client.RXMMongoDB


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.bind((IP, PORT))

s.listen(1)


#connections loop

while True:

conn, addr = s.accept()

print 'Connection address:',addr

try:

# read loop

while True:

data = server.recv(BUFFER_SIZE)


if not data:

break

# send to Mongo

mongodoc = { "data": data, "date" : datetime.datetime.utcnow() }

db..insert(mongodoc)

finally:

conn.close()





-- 
Mit freundlichen Grüßen / Thanks and Regards,


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


[Tutor] Extract several arrays from a large 2D array

2016-01-22 Thread Ek Esawi
Thank you all for your help. I am a decent programmer in another language
but new to Python and I have some issues with a project I am working on.
Some suggested using pandas but I am barley starting on Numpy. The
suggestions were very helpful, however, I decided to replace the 2D array
with several single arrays b/c the arrays are of different data types. I
ran into another problems and am almost done but got stuck.



Part of my code is below. The question is how to put the variables for each
j into a 14 by 6 array by a statement at the end of this code. I was hoping
to get an array like this one below:

 [2013 TT1 TT2 TT3 TT4 TT5 TT6]

 [2012TT1 TT2 TT3
TT4 TT5 TT6]

 .

 .

 [1999TT1 TT2 TT3
TT4 TT5 TT6]

for j in range(14)

for i in range(200):

if TYear[i]==2013-j:

if TTrea[i]=='T1':

TT1+=TTemp[i]

elif TTrea[i]=='T2':

TT2+=TTemp[i]

elif TTrea[i]=='T3':

TT3+=TTemp[i]

elif TTrea[i]=='T4':

TT4+=TTemp[i]

elif TTrea[i]=='T5':

TT5+=TTemp[i]

elif TTrea[i]=='T6':
TT6+=TTemp[i]
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB

2016-01-22 Thread Alan Gauld
On 21/01/16 22:06, Arjun Srivatsa wrote:
> Hello everyone,
> 
> I have been trying to insert data (a 'hello world' string) from PLC into
> MongoDB using Python API (which pulls the data from PLC and pushes it into
> MongoDB). I have been getting the error message '*line 222, in meth  return
> getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be
> made because the target machine actively refused it*' despite having mongod
> running in the Services background for the code I have written below. Also,
> the server IP address on which MongoDB is present is 10.52.124.186 and
> address of PLC (which I am using it on my PC) is 10.52.124.135. I am have
> tried almost everything to sort it out and yet I haven't got a clue as to
> how to get past it. Where am I going wrong?

This looks more like a MongoDB issue than a Python one.

Can you connect from the same machine using the Mongo
command line tools and options?

You might have more success asking on a Mongo support forum/list.


-- 
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] Extract several arrays from a large 2D array

2016-01-22 Thread Peter Otten
Ek Esawi wrote:

> Thank you all for your help. I am a decent programmer in another language
> but new to Python and I have some issues with a project I am working on.
> Some suggested using pandas but I am barley starting on Numpy. The
> suggestions were very helpful, however, I decided to replace the 2D array
> with several single arrays b/c the arrays are of different data types. I
> ran into another problems and am almost done but got stuck.
> 
> 
> 
> Part of my code is below. The question is how to put the variables for
> each j into a 14 by 6 array by a statement at the end of this code. I was
> hoping to get an array like this one below:
> 
>  [2013 TT1 TT2 TT3 TT4 TT5 TT6]
> 
>  [2012TT1 TT2 TT3
> TT4 TT5 TT6]
> 
>  .
> 
>  .
> 
>  [1999TT1 TT2 TT3
> TT4 TT5 TT6]
> 
> for j in range(14)
> 
> for i in range(200):

As a rule of thumb, if you are iterating over individual array entries in 
numpy you are doing something wrong ;)

> 
> if TYear[i]==2013-j:
> 
> if TTrea[i]=='T1':
> 
> TT1+=TTemp[i]
> 
> elif TTrea[i]=='T2':
> 
> TT2+=TTemp[i]
> 
> elif TTrea[i]=='T3':
> 
> TT3+=TTemp[i]
> 
> elif TTrea[i]=='T4':
> 
> TT4+=TTemp[i]
> 
> elif TTrea[i]=='T5':
> 
> TT5+=TTemp[i]
> 
> elif TTrea[i]=='T6':
> TT6+=TTemp[i]

This looks like you are manually building a pivot table. If you don't want 
to use a spreadsheet (like Excel or Libre/OpenOffice Calc) you can do it 
with pandas, too:

import pandas
import numpy
df = pandas.DataFrame(
[
[2013, "T1", 42],
[2013, "T2", 12],
[2012, "T1", 1],
[2012, "T1", 2],
[2012, "T2", 10],
[2012, "T3", 11],
[2012, "T4", 12],
],
columns=["year", "t", "v"])

print(
pandas.pivot_table(df, cols="t", rows="year", aggfunc=numpy.sum)
)

Here's a generic Python solution for educational purposes. It uses nested 
dicts to model the table. The outer dict is used for the rows, the inner 
dicts for the cells in a row. An extra set keeps track of the column labels.

data = [
[2013, "T1", 42],
[2013, "T2", 12],
[2012, "T1", 1],
[2012, "T1", 2],
[2012, "T2", 10],
[2012, "T3", 11],
[2012, "T4", 12],
]

table = {}
columns = set()
for year, t, v in data:
columns.add(t)
row = table.setdefault(year, {})
row[t] = row.get(t, 0) + v

columns = sorted(columns)
print("", *["{:>5}".format(c) for c in  columns])
for year, row in sorted(table.items(), reverse=True):
print(year, *["{:5}".format(row.get(c, 0)) for c in columns])


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


Re: [Tutor] No connection could be made because the target machine actively refused it (despite mongod running) and unable to insert data into MongoDB

2016-01-22 Thread Emile van Sebille

On 1/21/2016 2:06 PM, Arjun Srivatsa wrote:

Hello everyone,

I have been trying to insert data (a 'hello world' string) from PLC into
MongoDB using Python API (which pulls the data from PLC and pushes it into
MongoDB). I have been getting the error message '*line 222, in meth  return
getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be
made because the target machine actively refused it*' despite having mongod
running in the Services background for the code I have written below. Also,
the server IP address on which MongoDB is present is 10.52.124.186 and
address of PLC (which I am using it on my PC) is 10.52.124.135. I am have
tried almost everything to sort it out and yet I haven't got a clue as to
how to get past it. Where am I going wrong?



The error you're getting means that the firewall running on the mongod 
host machine is not properly configured to allow mongod traffic into it. 
 Talk to the machines firewall administrator.


Emile


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


Re: [Tutor] Tutor Digest, Vol 143, Issue 77

2016-01-22 Thread samuel kirwin
Semantic errors are when a program acts incorrectly and doesn't give a error, 
this came up yesterday.

Samuel Kirwin
Samvelk




On Fri, Jan 22, 2016 at 9:02 AM -0800,  wrote:





Send Tutor mailing list submissions to
tutor@python.org

To subscribe or unsubscribe via the World Wide Web, visit
https://mail.python.org/mailman/listinfo/tutor
or, via email, send a message with subject or body 'help' to
tutor-requ...@python.org

You can reach the person managing the list at
tutor-ow...@python.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Tutor digest..."


Today's Topics:

   1. Re: No connection could be made because the target machine
  actively refused it (despite mongod running) and unable to insert
  data into MongoDB (Emile van Sebille)


--

Message: 1
Date: Fri, 22 Jan 2016 06:37:19 -0800
From: Emile van Sebille 
To: tutor@python.org
Subject: Re: [Tutor] No connection could be made because the target
machine actively refused it (despite mongod running) and unable to
insert data into MongoDB
Message-ID: 
Content-Type: text/plain; charset=utf-8; format=flowed

On 1/21/2016 2:06 PM, Arjun Srivatsa wrote:
> Hello everyone,
>
> I have been trying to insert data (a 'hello world' string) from PLC into
> MongoDB using Python API (which pulls the data from PLC and pushes it into
> MongoDB). I have been getting the error message '*line 222, in meth  return
> getattr(self._sock,name)(*args) error: [Errno 10061] No connection could be
> made because the target machine actively refused it*' despite having mongod
> running in the Services background for the code I have written below. Also,
> the server IP address on which MongoDB is present is 10.52.124.186 and
> address of PLC (which I am using it on my PC) is 10.52.124.135. I am have
> tried almost everything to sort it out and yet I haven't got a clue as to
> how to get past it. Where am I going wrong?


The error you're getting means that the firewall running on the mongod
host machine is not properly configured to allow mongod traffic into it.
  Talk to the machines firewall administrator.

Emile




--

Subject: Digest Footer

___
Tutor maillist  -  Tutor@python.org
https://mail.python.org/mailman/listinfo/tutor


--

End of Tutor Digest, Vol 143, Issue 77
**
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Combine Scripts to Work Together...

2016-01-22 Thread Sam Starfas via Tutor



 Hi,I am new to Python, but learning. (Hopefully the layout is readable)
I am having trouble getting two scripts to work together. What I want to do is 
have the combinded script do the following:
1. Read through a directory of xml files, not a single file, but many xml 
files.2. Read each files contents.3. Pull out the  element content 
(words between open and close tag)
   * For example: Sam was here.
   * The script would pull out the content "Sam was here" and print it to a 
file.

My scripts so 
far:--Script to get 
 
content--import 
xml.etree.ElementTree as ET
tree = ET.parse('TEST.xml')
root = tree.getroot()for uicontrol in root.iter('uicontrol'):
 print(uicontrol.text)
--Script to read 
through the 
files:--import sys
import glob
import errnopath 
='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml'
   files = glob.glob(path)  
for name in files: # 'file' is a builtin type, 'name' is a 
less-ambiguousvariable name.
 try:
   with open(name) as f: # Noneed to specify 'r': this is the default.
   sys.stdout.write(f.read())

This is the area I get stuck. I can understand, write a script to run on one a 
single file you input into the script, but getting a script to run on a 
directory I am not understanding how to do this.
Thanks in advance for any and all help.Really appreciate the help.
Sam

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


[Tutor] Semantic error (was: Re: Tutor Digest, Vol 143, Issue 77)

2016-01-22 Thread Alan Gauld
On 22/01/16 17:05, samuel kirwin wrote:
> Semantic errors are when a program acts incorrectly and doesn't give a error, 
> this came up yesterday.
> 
> Samuel Kirwin

Hi Sam, Thanks for participating.

However, it will make your comments more meaningful if you
reply with the subject line set to whatever tread you were
responding to. Also if using the digest please delete all
irrelevant messages/content. That way we can see the context.
We've all seen them already and some of us pay by the byte.

As it is, the above statement just seems like a fairly random
comment. After all, the word semantic does not occur anywhere
within the glossary messages you forwarded.

-- 
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] Combine Scripts to Work Together...

2016-01-22 Thread Joel Goldstick
On Fri, Jan 22, 2016 at 1:16 PM, Sam Starfas via Tutor 
wrote:

>
>
>
>  Hi,I am new to Python, but learning. (Hopefully the layout is readable)
> I am having trouble getting two scripts to work together. What I want to
> do is have the combinded script do the following:
> 1. Read through a directory of xml files, not a single file, but many xml
> files.2. Read each files contents.3. Pull out the  element
> content (words between open and close tag)
>* For example: Sam was here.
>* The script would pull out the content "Sam was here" and print it to
> a file.
>
> My scripts so
> far:--Script to get
> 
> content--import
> xml.etree.ElementTree as ET
> tree = ET.parse('TEST.xml')
> root = tree.getroot()for uicontrol in root.iter('uicontrol'):
>  print(uicontrol.text)
>

Make the above a function
def get_uicontrol(f):

> tree = ET.parse(f))
> root = tree.getroot()for uicontrol in root.iter('uicontrol'):
>  print(uicontrol.text)
>

--Script to read
> through the
> files:--import sys
> import glob
> import errnopath
> ='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml'
> files = glob.glob(path)
> for name in files: # 'file' is a builtin type, 'name' is a
> less-ambiguousvariable name.
>  try:
>with open(name) as f: # Noneed to specify 'r': this is the
> default.
>sys.stdout.write(f.read())
>
>
Make the above a function:

def get_files(path):
glob.glob(path)
for name in files:
 try:
  with open(name) as f
  get_uicontrol(f)

then at the end of your file do this:

if __name__ == '__main__':
get_files('/your/path/goes/here')

get_files will loop to open each file, then call get_uicontrol on that open
file.  get_uicontrol will find your tag, collect the text and print it

I haven't tested this, but it is at least close


> This is the area I get stuck. I can understand, write a script to run on
> one a single file you input into the script, but getting a script to run on
> a directory I am not understanding how to do this.
> Thanks in advance for any and all help.Really appreciate the help.
> Sam
>
>
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>



-- 
Joel Goldstick
http://joelgoldstick.com/stats/birthdays
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Combine Scripts to Work Together...

2016-01-22 Thread Joel Goldstick
On Fri, Jan 22, 2016 at 1:48 PM, Joel Goldstick 
wrote:

>
>
> On Fri, Jan 22, 2016 at 1:16 PM, Sam Starfas via Tutor 
> wrote:
>
>>
>>
>>
>>  Hi,I am new to Python, but learning. (Hopefully the layout is readable)
>> I am having trouble getting two scripts to work together. What I want to
>> do is have the combinded script do the following:
>> 1. Read through a directory of xml files, not a single file, but many xml
>> files.2. Read each files contents.3. Pull out the  element
>> content (words between open and close tag)
>>* For example: Sam was here.
>>* The script would pull out the content "Sam was here" and print it to
>> a file.
>>
>> My scripts so
>> far:--Script to get
>> 
>> content--import
>> xml.etree.ElementTree as ET
>> tree = ET.parse('TEST.xml')
>> root = tree.getroot()for uicontrol in root.iter('uicontrol'):
>>  print(uicontrol.text)
>>
>
> Make the above a function
> def get_uicontrol(f):
>
>> tree = ET.parse(f))
>> root = tree.getroot()for uicontrol in root.iter('uicontrol'):
>>  print(uicontrol.text)
>>
>
> --Script to read
>> through the
>> files:--import sys
>> import glob
>> import errnopath
>> ='/Users/sastarfa/Documents/Projects/Script-projects/Scripts/Pull-out-terms-between-elements/*.xml'
>> files = glob.glob(path)
>> for name in files: # 'file' is a builtin type, 'name' is a
>> less-ambiguousvariable name.
>>  try:
>>with open(name) as f: # Noneed to specify 'r': this is the
>> default.
>>sys.stdout.write(f.read())
>>
>>
> Make the above a function:
>
> def get_files(path):
> glob.glob(path)
> for name in files:
>  try:
>   with open(name) as f:
>   get_uicontrol(f)
>
> oops, edited above two lines


> then at the end of your file do this:
>
> if __name__ == '__main__':
> get_files('/your/path/goes/here')
>
> get_files will loop to open each file, then call get_uicontrol on that
> open file.  get_uicontrol will find your tag, collect the text and print it
>
> I haven't tested this, but it is at least close
>
>
>> This is the area I get stuck. I can understand, write a script to run on
>> one a single file you input into the script, but getting a script to run on
>> a directory I am not understanding how to do this.
>> Thanks in advance for any and all help.Really appreciate the help.
>> Sam
>>
>>
>> ___
>> Tutor maillist  -  Tutor@python.org
>> To unsubscribe or change subscription options:
>> https://mail.python.org/mailman/listinfo/tutor
>>
>
>
>
> --
> Joel Goldstick
> http://joelgoldstick.com/stats/birthdays
>



-- 
Joel Goldstick
http://joelgoldstick.com/stats/birthdays
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] mock

2016-01-22 Thread Alex Kleider

Some weeks (perhaps months) ago, I posted a question about testing
and got many responses but had trouble grasping the concepts
so I settled on the suggestion that I thought would be the easiest
to implement (using unittest.mock.) Here it is-

"""
from Peter Otten:
I find Ben's example instructive, but when you're just starting you
might prefer a simpler approach:

import unittest
from unittest import mock
import mycode

class TestCollectData(unittest.TestCase):
def test(self):
with mock.patch(
"builtins.input",
side_effect=["foo", "bar", "baz"]):
self.assertEqual(
mycode.collect_data(),
dict(first="foo", last="bar", phone="baz"))

if __name__ == "__main__":
unittest.main()
"""

I've successfully implemented mock.patch parameters but don't
understand how to implement the parameters for the assertEqual
call as it pertains to my particular situation.

My current code sort of does the job but determinating success or
failure is not really automated.

It's Python 3 on Ubuntu 14.4LTS.
My test code and the tested code follow.  Any suggestions would be
most welcome.  Thanks in advance.
Alex

Test Code:
#!../../venv/bin/python
# -*- coding: utf-8 -*-
# vim: set file encoding=utf-8
"""
Attempt to automate testing of menu module.
"""
import unittest
from unittest import mock
import menu

class MenuTests(unittest.TestCase):

def test_create_new(self):
with mock.patch("builtins.input",
side_effect=['1', 'testentity', '', '0']):
menu.menu()

if __name__ == '__main__':  # code block to run the application
unittest.main()


Tested code:

#!../../venv/bin/python
# -*- coding: utf-8 -*-
# vim: set file encoding=utf-8
"""
A simple menu model used to format a question
about how to test using unittest.mock.
"""

class Entities(object):
"""
Keep track of the entities including a default.
Expect only one instance which will be a global.
"""

def __init__(self, list_of_entities, default=''):
self._list = list_of_entities
self.default = default

def get_default(self):
return self.default

def reset_default(self, default=''):
self.default = default

def get_list(self):
return self._list

def add(self, new_entity, set_default=False):
"""
Adds another entity returning it to signal success.
Returns None if entity is unacceptable.
"""
if (not new_entity in self._list
and new_entity.isalnum()
and new_entity[0:1].isalpha()):
self._list.append(new_entity)
if set_default:
self.reset_default(new_entity)
return new_entity
else:
print("Failing to add an invalid entity: '{}'."
.format(new_entity))

def get_new_entity(self):
"""
Prompts user for a new entity which, if valid, is
returned after being appended to list and set as default.
Returns None if fails to create a new entity.
"""
while True:
new_entity = input("Pick name for new entity: ")
if not new_entity: return
if new_entity != self.add(new_entity, set_default=True):
continue
else:
return new_entity

def remove(self, entity2remove):
if not entity2remove in self.get_list():
print("Can't remove '{}': not in the list."
.format(entity2remove))
return
if entity2remove == self.get_default():
self.reset_default()
self._list = [entity for entity in self._list
if entity!=entity2remove]

def show_listing(self):
"""
Returns a string listing the available entities.
Empty string if there are no entities.
"""
return ''.join(["\n\t{}".format(entity)
for entity in self.get_list()])

def entity_choice(self, set_default=False):
"""
Prompts the user to choose from the list.
Returns a valid choice or None.
Can optionally set the default to the chosen entity.
"""
list_of_entities= self.get_list()
if not list_of_entities:
print("There are no entities from which to choose.")
return
default_line = ''
 if self.default:
default_line = ("\n\t_: Default is '{}', just hit enter."
.format(self.default))
menu = ('\n'.join(["\t{}: {}".format(n, entity)
for (n, entity) in enumerate(list_of_entities, 1)])
+ default_line)
while True:
option = input(
"""Choose one of the following:
{}
\t0: to exit.
Pick an entity: """.format(menu))
default = self.get_default()
if (option=='' or option=='_') and default:
  

Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-22 Thread boB Stepp
On Thu, Jan 21, 2016 at 4:57 AM, Steven D'Aprano  wrote:
> On Wed, Jan 20, 2016 at 09:54:32PM -0800, Danny Yoo wrote:
>
>> Just to be explicit: you are pointing out that:
>>
>>  humdrum.sigh_strenght = 'high'
>>
>> was a typo, and it would have been nice if it could be caught as an error.
>>
>> If that's the case, then yes, I agree.  Unfortunately, this isn't a
>> runtime error because Python allows us to add arbitrary attributes to
>> objects: it's a deliberate design feature.
>
> Danny is correct. And it is a useful feature too. For instance, we can
> add attributes to functions:
>
> def spam(x, y):
> ...
>
> spam.extra_info = "whatever"

A new thing that I did not suspect I could do.  This bothers me for two reasons:

1)  It does not seem right adding attributes to functions outside
of its definition.

2)  spam.extra_info appears to be global:

>>> spam.extra_info = "whatever"
>>> z = 'WOW!'
>>> def print_global_stuff():
print('z =', z)
print('spam.extra_info =', spam.extra_info)

>>> print_global_stuff()
z = WOW!
spam.extra_info = whatever

And I imagine I am being dense about something that is quite obvious
to you:  How is this a useful feature to have?  What does it give me
that is more useful than just saying something like:

just_another_global variable = "whatever"

?

And what bothered me about my original example that started this
thread is that when my typo

humdrum.sigh_strenght = 'high'

was accepted and did not generate an error, it seemed to mean to me
that I was violating my object's data encapsulation.  It just seems to
me that I should not be able to arbitrarily add new attributes from
outside the class definition that created my object.  That seems
similar to having a class Dog, to which from outside the class'
definition, I decide to add a new Dog attribute that all dogs in this
class can now have a tail sticking out of their noses.  I have no
qualms about subclassing Dog with a MutantDog subclass, but adding new
attributes from outside the class definition?  That just does not seem
right to at this point of my understanding.  As in your function
example, I am sure that I am missing something quite obvious, but I am
just not seeing it now.

Keep in mind, that I am just now this past week starting to study
classes.  All of my programming experience has been strictly
procedural Other than dabbling in Tkinter at work.).  I have no
pre-experience with Java or C++, other than casual reading, so any
preconceptions I have come from my procedural background ages ago in
FORTRAN.


> Other advantages of this way of doing things include that you aren't
> forced to put all your initialisation code in a single, special place,
> you can factor parts of it out into alternative methods:
>
> class X:
>def __init__(self, x):
>self.setup(x)
>def setup(self, x):
>process(x)
>self.attribute = x
>

I have seen this before and agree that this is both useful and
desirable.  But I am comfortable with this because it is happening
*inside* the class definition.

> It also means that Python doesn't require a magic "undefined" value,
> like Javascript has, or require declarations ahead of time, like static
> languages such as Pascal and C require.

I have come to enjoy this feature of Python as well!

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


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-22 Thread Cameron Simpson

On 22Jan2016 22:14, boB Stepp  wrote:

On Thu, Jan 21, 2016 at 4:57 AM, Steven D'Aprano  wrote:

Danny is correct. And it is a useful feature too. For instance, we can
add attributes to functions:

def spam(x, y):
...

spam.extra_info = "whatever"


A new thing that I did not suspect I could do.  This bothers me for two reasons:

   1)  It does not seem right adding attributes to functions outside
of its definition.


Have you tried to do it from inside? Anyway, a function is just another object. 
What do you think it should be particularly special?



   2)  spam.extra_info appears to be global:


spam.extra_info = "whatever"
z = 'WOW!'
def print_global_stuff():

   print('z =', z)
   print('spam.extra_info =', spam.extra_info)


No, "spam" is global. So you can name it anywhere in that module; therefore you 
can name anything inside it. Again, like any other object.



print_global_stuff()

z = WOW!
spam.extra_info = whatever

And I imagine I am being dense about something that is quite obvious
to you:  How is this a useful feature to have?  What does it give me
that is more useful than just saying something like:

just_another_global variable = "whatever"


spam.extra_info = "blah"
snot = spam
print(snot.extra_info)

Consider if you passed "snot" (or "spam") to a function:

 def print_extra_info(obj):
   print(obj.extra_info)

This is not something you could do with just_another_global_variable.

Consider: this is information you want assicated with a specific object.  
Therefore it really _is_ an arribute of the object so that it can follow it 
around.



And what bothered me about my original example that started this
thread is that when my typo

humdrum.sigh_strenght = 'high'

was accepted and did not generate an error, it seemed to mean to me
that I was violating my object's data encapsulation.  It just seems to
me that I should not be able to arbitrarily add new attributes from
outside the class definition that created my object.  That seems
similar to having a class Dog, to which from outside the class'
definition, I decide to add a new Dog attribute that all dogs in this
class can now have a tail sticking out of their noses.  I have no
qualms about subclassing Dog with a MutantDog subclass, but adding new
attributes from outside the class definition?  That just does not seem
right to at this point of my understanding.  As in your function
example, I am sure that I am missing something quite obvious, but I am
just not seeing it now.


All you're missing is realising that setting an attribute is not a special 
operation.


To take an anecdote from elsewhere:

 UNIX was not designed to stop you from doing stupid things, because that 
 would also stop you from doing clever things.   - Doug Gwyn


There's no need to prevent you setting "sigh_strenght". There probably is 
benefit in linting tools reporting to you about attributes which are set but 
apparently never used.


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


Re: [Tutor] Why is the name "self" optional instead of mandatory?

2016-01-22 Thread boB Stepp
On Thu, Jan 21, 2016 at 5:49 AM, Steven D'Aprano  wrote:
> On Wed, Jan 20, 2016 at 09:42:29PM -0600, boB Stepp wrote:
>
>> So I really only have one question:  Why not make Python's
>> *traditional* name, "self", mandatory?  Why give the programmer this
>> kind of choice?  [OK, that was two questions.]
>
> Why bother making it mandatory? That just makes more work for the
> compiler -- it has to decide that a function is inside a class, and
> therefore apply a restriction to the first argument. Most of the time,
> giving the programmer more freedom is less work.
>
> And what happens if you do this?
>
> class X:
> pass
>
> def func(this):
> print("instance %r called method" % this)
>
> X.method = func

Am I understanding this correctly?  It appears to me that you have
successfully added a method to class X from outside of class X!  If
this is the case, then this clarifies some things I was wondering
about in my other thread.

> And what are we supposed to do with classmethods and staticmethods? They
> shouldn't take a "self" argument at all, but they start off life as a
> regular function, just like ordinary instance methods.
>
> And of course, there are Metaclasses. You might need a metaclass method
> that needs to deal with all three levels of the hierarchy: the
> metaclass, the class it creates, and the instance of that class.
>
> class Meta(type):
> def metamethod(meta, cls, self):
> ...

I scanned the article that Danny gave a link to.  I am not ready to go
in depth into these concepts at this time, but I cannot help but
wonder about the possibilities these concepts open up?  At work I find
myself writing Python to generate correct scripting language commands
for the proprietary software I use at work.  What if I could write a
Python program which thoroughly captured the entire proprietary
scripting language into a much easier to use interface?  Their
scripting language has an underlying OO structure that is not exposed
to my prying eyes.  But *if* I could create a class structure that was
sufficiently similar to theirs that it seamlessly generated the
correct messages that their OOP style uses, then things might be much
easier for my projects.  Hmm...

I guess I am trying to wrap my mind around this incredible power and
flexibility that Python provides.  I thought I had asked a relatively
harmless question.  But it generated some strong responses!  It seemed
like "self" had a similar utility of use as "print" to me.  After all,
we can't redefine "print", can we?  But now I realize that I can do
exactly that if I so choose.  That is both fascinating and scary!
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-22 Thread boB Stepp
On Fri, Jan 22, 2016 at 11:04 PM, Cameron Simpson  wrote:
> On 22Jan2016 22:14, boB Stepp  wrote:

[...]

> Consider: this is information you want assicated with a specific object.
> Therefore it really _is_ an arribute of the object so that it can follow it
> around.
>
>> And what bothered me about my original example that started this
>> thread is that when my typo
>>
>> humdrum.sigh_strenght = 'high'
>>
>> was accepted and did not generate an error, it seemed to mean to me
>> that I was violating my object's data encapsulation.  It just seems to
>> me that I should not be able to arbitrarily add new attributes from
>> outside the class definition that created my object.  That seems
>> similar to having a class Dog, to which from outside the class'
>> definition, I decide to add a new Dog attribute that all dogs in this
>> class can now have a tail sticking out of their noses.  I have no
>> qualms about subclassing Dog with a MutantDog subclass, but adding new
>> attributes from outside the class definition?  That just does not seem
>> right to at this point of my understanding.  As in your function
>> example, I am sure that I am missing something quite obvious, but I am
>> just not seeing it now.
>
>
> All you're missing is realising that setting an attribute is not a special
> operation.

I guess no matter how new one is to OOP, one nevertheless brings one's
preconceptions, however malformed, into the learning process.  In my
case, one of mine was that once a class is coded, any given instance
of a class is forevermore responsible for managing its *internals*, so
that any change in these would be managed by the object when one of
its (meant to be) publicly available methods is called.  In the case
of attributes, I was thinking/expecting something like the following
would have to be done:

>>> class Dog(object):
def __init__(self, name, breed):
self.name = name
self.breed = breed
self.number_legs = 4
self.number_tails = 1
self.number_eyes = 2
self.attributes = {
'name': self.name,
'breed': self.breed,
'number of legs': self.number_legs,
'number of tails': self.number_tails,
'number of eyes': self.number_eyes}

def add_attribute(self, new_attribute_name, new_attribute_value):
self.new_attribute_name = new_attribute_name
self.new_attribute_value = new_attribute_value
self.attributes[self.new_attribute_name] = self.new_attribute_value

def show_attributes(self):
print("The object,", self.name, "has the following attributes:")
for attribute_name, attribute_value in self.attributes.items():
print(attribute_name, "=", attribute_value)

>>> our_dog = Dog('Copper', 'beagle')
>>> our_dog.show_attributes()
The object, Copper has the following attributes:
number of tails = 1
number of legs = 4
breed = beagle
name = Copper
number of eyes = 2
>>> our_dog.add_attribute('unique marking', 'blue right eye')
>>> our_dog.show_attributes()
The object, Copper has the following attributes:
number of legs = 4
breed = beagle
unique marking = blue right eye
number of tails = 1
name = Copper
number of eyes = 2

I suspect there are probably better ways to do what I am trying to
demonstrate [I am trying to use a dict to simulate adding new instance
variables after the fact.], perhaps with built-in functions that I
have not read about yet.  But I hope my code illustrates my previous
expectations.  I guess I was expecting that access to an object's
internals would be more strictly regulated.  But, thinking about it, I
already knew that even if name mangling is done for a method's name,
it can still be directly accessed from outside of that object's class
definition.

But if I am understanding everyone's comments correctly, Python allows
me write my classes in such a way, that public access to my object's
internals is controlled, in the sense that Python has coding
conventions that tell all of the quite intelligent, respectful,
consenting adults that might use my code how I intend that code to be
used.  And that I, despite my intentions, must respect that users of
my code may have very valid reasons for deviating from my intentions.
Have I captured the Pythonic spirit of what everyone has been trying
to tell me?

Thanks for your patience, now and in the future, as I try to learn OOP
in Python!

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