Re: [Tutor] class attribute to initiate more classes
Vincent Davis wrote: I have a program that generates many instances of a class with an attribute self.x = random.gauss(10, 2). So each instance has a different value for self.x. This is what I want. Now I want to make a class that starts my program and sets the attributes. class people: def __init__(self, size) self.size = size class makepeople: def __init__(self, randomsize) self.rsize = randomsize self.allpeople = [] def makethem(): for x in range(1,100): p+str(x) = people(self.rsize) allpeople.append(p+str(x)) so what I would like to have work is set the attribute of makepeople so that when it is used to make instances of people each will have a different size. listofp = makepeople(random.guass(100, 2)) listofp.makethem() I would then what listofp.allpeople to be a list of people with different sizes. The above code does not work, I don't think it does anyway. I hope this makes sense, I am sure there is a term for what I am trying to do but I don't know it. Thanks Vincent Davis You're trying to do several things here, and I'm unclear on many of the details. So here's a new spec, and the implementation for it. We want a factory class, which can be given a particular distribution function and parameters, and using those parameters generate a list of Person objects, whose heights are distributed according to that random function. There might be duplicates in that list, but they'd be random coincidence, and the list as a whole would be as random as the function specified by the caller. I also took a few liberties on the names of things, trying to use Python conventions for naming, and things like using a singular word for a classname of a single item. And I removed the allpeople attribute, as the class only makes sense to me if you can use its instance multiple times, to generate more items with the same given distribution. CODE import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person /CODE--- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] problem adding Tkinter
"Kristin Wilcox" wrote [This is my problem:] I've been using IDLE successfully to do very very simple exercises in Python, and now I wanted to start on some very simple exercises including the Tkinter library. Which vwersuion of Python are you using? In version 3 Tkinter has been renamed to tkinter I could do import _tkinter but not import Tkinter This is what I received back from the Shell: import _tkinter import Tkinter Traceback (most recent call last): File "", line 1, in import Tkinter ImportError: No module named Tkinter Try import tkinter if you are using v3. I am running Windows XP. Installed Python 3.1, and IDLE seems to be working okay... OK Thats the problem, you need tkinter not Tkinter. But if you are still at that stage of learning you might be better downgrading to Python v2.7. Python 3.1 is getting there but its not quite ready for beginners use just yet (IMHO). HTH, -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/l2p/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
On Sat, Oct 31, 2009 at 1:01 AM, Vincent Davis wrote: > I have a program that generates many instances of a class with an attribute > self.x = random.gauss(10, 2). So each instance has a different value for > self.x. This is what I want. Now I want to make a class that starts my > program and sets the attributes. > class people: > def __init__(self, size) > self.size = size > class makepeople: > def __init__(self, randomsize) > self.rsize = randomsize > self.allpeople = [] > def makethem(): > for x in range(1,100): > p+str(x) = people(self.rsize) > allpeople.append(p+str(x)) > so what I would like to have work is set the attribute of makepeople so that > when it is used to make instances of people each will have a different size. > listofp = makepeople(random.guass(100, 2)) Here you are calling makepeople() and passing it a single random number that will be used for all people. You need to call random.gauss() in the loop. > listofp.makethem() > I would then what listofp.allpeople to be a list of people with different > sizes. The above code does not work, I don't think it does anyway. > I hope this makes sense, I am sure there is a term for what I am trying to > do but I don't know it. I would just make a function that creates the list of people. There is no need to put it in a class. For example, def make_people(): return [people(random.gauss(100,2)) for x in range(1, 100)] # Note this only makes 99 people Kent ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
DaveA posted import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person.size I changed the last line, from print person print person.size So this does what I want, but I am not sure why. I read the entry about functools.partial but it was not very clear to me. If I people_maker = MakePeople(random.gauss(100, 2)) then I only get 1 random #. and if I MakePeople('random.gauss(100, 2)') then I just a fix string So DaveA uses functools.partial(random.gauss, 100, 2) not obvious to me from that it should not be functools.partial(random.gauss(100, 2)) and I guess the other key is Person(self.random_func()) Also now this people_maker = MakePeople(123) does not work, which is not terrible. Anyone have some more to add, I would not have confidence in applying this to new situations and it seems. Also I thank DaveA improving my Python conventions. I am really bad about that. Is there a cheat sheet for Python conventions. Like class (Capitals), def (two_words), I guess I should make my own. Thanks Vincent Davis 720-301-3003 On Sat, Oct 31, 2009 at 5:55 AM, Dave Angel wrote: > Vincent Davis wrote: > >> I have a program that generates many instances of a class with an >> attribute >> self.x = random.gauss(10, 2). So each instance has a different value for >> self.x. This is what I want. Now I want to make a class that starts my >> program and sets the attributes. >> class people: >>def __init__(self, size) >>self.size = size >> >> class makepeople: >>def __init__(self, randomsize) >>self.rsize = randomsize >>self.allpeople = [] >>def makethem(): >>for x in range(1,100): >>p+str(x) = people(self.rsize) >>allpeople.append(p+str(x)) >> >> so what I would like to have work is set the attribute of makepeople so >> that >> when it is used to make instances of people each will have a different >> size. >> >> listofp = makepeople(random.guass(100, 2)) >> listofp.makethem() >> >> I would then what listofp.allpeople to be a list of people with different >> sizes. The above code does not work, I don't think it does anyway. >> >> I hope this makes sense, I am sure there is a term for what I am trying to >> do but I don't know it. >> >> Thanks >> Vincent Davis >> >> >> > You're trying to do several things here, and I'm unclear on many of the > details. So here's a new spec, and the implementation for it. > > We want a factory class, which can be given a particular distribution > function and parameters, and using those parameters generate a list of > Person objects, whose heights are distributed according to that random > function. There might be duplicates in that list, but they'd be random > coincidence, and the list as a whole would be as random as the function > specified by the caller. > > I also took a few liberties on the names of things, trying to use Python > conventions for naming, and things like using a singular word for a > classname of a single item. And I removed the allpeople attribute, as the > class only makes sense to me if you can use its instance multiple times, to > generate more items with the same given distribution. > > > CODE > import random, functools > > class Person: > > def __init__(self, size): > self.size = size > def __str__(self): > return "Person of size %s" % self.size > > class MakePeople: > def __init__(self, random_func): > self.random_func = random_func > > def make_them(self, count): > return [Person(self.random_func()) for i in xrange(count)] > > > people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) > persons = people_maker.make_them(100) > for person in persons: > print person > > /CODE--- > > DaveA > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] class attribute to initiate more classes
(You top-posted, which confuses the sequence of message text. So I clipped it off and posted my message at the bottom, which is the convention on this newsgroup) Vincent Davis wrote: DaveA posted import random, functools class Person: def __init__(self, size): self.size = size def __str__(self): return "Person of size %s" % self.size class MakePeople: def __init__(self, random_func): self.random_func = random_func def make_them(self, count): return [Person(self.random_func()) for i in xrange(count)] people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) persons = people_maker.make_them(100) for person in persons: print person.size I changed the last line, from print person print person.size So this does what I want, but I am not sure why. I read the entry about functools.partial but it was not very clear to me. If I people_maker = MakePeople(random.gauss(100, 2)) then I only get 1 random #. and if I MakePeople('random.gauss(100, 2)') then I just a fix string So DaveA uses functools.partial(random.gauss, 100, 2) not obvious to me from that it should not be functools.partial(random.gauss(100, 2)) and I guess the other key is Person(self.random_func()) Also now this people_maker = MakePeople(123) does not work, which is not terrible. Anyone have some more to add, I would not have confidence in applying this to new situations and it seems. Also I thank DaveA improving my Python conventions. I am really bad about that. Is there a cheat sheet for Python conventions. Like class (Capitals), def (two_words), I guess I should make my own. Thanks Vincent Davis 720-301-3003 For the official Python style guide, see http://www.python.org/dev/peps/pep-0008/ There are a couple of things going on in my code sample, and I'll try to elaborate on them. I'm not claiming it's the 'right' answer, just that it satisfies what I think were the most important goals you had. But if you want to save the list in the MakePeople() instance, you'd add an additional parameter to its constructor, and combine the second method into __init__(). But as someone else points out, at that point, it's then hardly worth making a class out of it. First the tough part. In your original code, your caller was doing: listofp = makepeople(random.guass(100, 2)) But that passes only a single value into the makepeople constructor. If you're always going to use gaussian, then you can just move the function call into the make_them() loop. But if you want to do the same thing, but with a different distribution, you need to pass a function object instead. Learning about function objects is very useful. You should really play with them in a simpler situation, to get an idea how they work. At its simplest, a function object is just the function name, without parentheses. You can store it (and pass it as a parameter to another function) just like any other object. And then when you actually want to call it, you can use the new name with parentheses, kind of like an alias to the original function name. import math def indirection(funcobject, argument): return funcobject(math.pi/180 * argument) print indirection(math.sin, 30) print indirection(math.cos, 30) Now what happens here? The indirection() function calls an entirely different function the two times it's called, one time it calls sin, and the other time it calls cos. As long as all the arguments to the function are going to be supplied here, there's no confusion. Try the same thing with any other set of functions, given that all of them take the same number and types of arguments. This opens the door to all sorts of things, such as a mini-calculator (following is mostly pseudo-code): funcname = getnamefrom user() angleinradians = getnumberfromuser() converter_dict = { "sin": math.sin, "cos":math.cos } print converter_dict[funcname](angleinradians) So the values of the dictionary are actual function objects, ready to be called. What happens if some of the function parameters are known to the caller, and not to the callee? I'll use the random.gauss example again. If we want the caller to be able to specify them, we could do something like the following: def print_indirection(funcobject, arg1, arg2, count): for i in xrange(count): print funcobject(arg1, arg2) and call it: print_indirection(random.gauss, 100, 2, 44) to get 44 values with a gaussian distributon. But now suppose we wanted to be able to use the same function with random.getrandbits() ? That function only takes a single parameter, so the print funcobject() would blow up. functools.partial lets us bind a function object with some or all of its arguments already attached. So in our case, the caller (who knows what the arguments look like) gets to lay them out, without being stuck with any particular ones. So, we rewrite print_indirection something like thi
Re: [Tutor] class attribute to initiate more classes
> > > Vincent Davis wrote: > >> DaveA posted >> import random, functools >> >> class Person: >>def __init__(self, size): >>self.size = size >> >>def __str__(self): >>return "Person of size %s" % self.size >> >> class MakePeople: >>def __init__(self, random_func): >>self.random_func = random_func >> >>def make_them(self, count): >>return [Person(self.random_func()) for i in xrange(count)] >> >> people_maker = MakePeople(functools.partial(random.gauss, 100, 2)) >> persons = people_maker.make_them(100) >> for person in persons: >>print person.size >> >> I changed the last line, from >> print person >> print person.size >> >> So this does what I want, but I am not sure why. >> I read the entry about functools.partial but it was not very clear to me. >> If I >> people_maker = MakePeople(random.gauss(100, 2)) >> then I only get 1 random #. >> and if I >> MakePeople('random.gauss(100, 2)') >> then I just a fix string >> So DaveA uses >> >> functools.partial(random.gauss, 100, 2) >> >> not obvious to me from that it should not be >> >> functools.partial(random.gauss(100, 2)) >> >> and I guess the other key is >> >> Person(self.random_func()) >> >> Also now this >> people_maker = MakePeople(123) >> >> does not work, which is not terrible. >> >> Anyone have some more to add, I would not have confidence in applying this >> to new situations and it seems. >> >> Also I thank DaveA improving my Python conventions. I am really bad about >> that. Is there a cheat sheet for Python conventions. >> >> Like class (Capitals), def (two_words), I guess I should make my own. >> >> Thanks >> Vincent Davis >> 720-301-3003 >> >> >> >> >> > For the official Python style guide, see > http://www.python.org/dev/peps/pep-0008/ > > There are a couple of things going on in my code sample, and I'll try to > elaborate on them. I'm not claiming it's the 'right' answer, just that it > satisfies what I think were the most important goals you had. But if you > want to save the list in the MakePeople() instance, you'd add an additional > parameter to its constructor, and combine the second method into __init__(). > But as someone else points out, at that point, it's then hardly worth > making a class out of it. > > First the tough part. In your original code, your caller was doing: > > > > listofp = makepeople(random.guass(100, 2)) > > But that passes only a single value into the makepeople constructor. If > you're always going to use gaussian, then you can just move the function > call into the make_them() loop. But if you want to do the same thing, but > with a different distribution, you need to pass a function object instead. > Learning about function objects is very useful. You should really play > with them in a simpler situation, to get an idea how they work. > > At its simplest, a function object is just the function name, without > parentheses. You can store it (and pass it as a parameter to another > function) just like any other object. And then when you actually want to > call it, you can use the new name with parentheses, kind of like an alias to > the original function name. > > import math > > def indirection(funcobject, argument): > return funcobject(math.pi/180 * argument) > > print indirection(math.sin, 30) > print indirection(math.cos, 30) > > > Now what happens here? The indirection() function calls an entirely > different function the two times it's called, one time it calls sin, and the > other time it calls cos. As long as all the arguments to the function are > going to be supplied here, there's no confusion. Try the same thing with > any other set of functions, given that all of them take the same number and > types of arguments. > > This opens the door to all sorts of things, such as a mini-calculator > (following is mostly pseudo-code): > > funcname = getnamefrom user() > angleinradians = getnumberfromuser() > > converter_dict = { "sin": math.sin, "cos":math.cos } > print converter_dict[funcname](angleinradians) > > So the values of the dictionary are actual function objects, ready to be > called. > > What happens if some of the function parameters are known to the caller, > and not to the callee? I'll use the random.gauss example again. If we want > the caller to be able to specify them, we could do something like the > following: > > def print_indirection(funcobject, arg1, arg2, count): > for i in xrange(count): > print funcobject(arg1, arg2) > > and call it: > print_indirection(random.gauss, 100, 2, 44) > > to get 44 values with a gaussian distributon. But now suppose we wanted to > be able to use the same function with random.getrandbits() ? That function > only takes a single parameter, so the print funcobject() would blow up. > > functools.partial lets us bind a function object with some or all of its > arguments already attached. So in our case, the caller (who knows what the > arguments look like) gets to lay them out,
[Tutor] Structure of my simulation / monte-carlo
I ask this question in part because of a fee remarks from another question I ask "class attribute to initiate more classes" Basically I am simulation the process of applicants to schools and trying to ask/answer some questions like "what conditions do you need to have an optimal solution" Oh and to learn python. I basically had it working as a script rather than using a class structure but it was very inflexible and I still needed to learn about classes. What I have these classes class Applicant: has lots of attributes (self.gpa = random.gauss(50, 10) about the Applicant and def() defining how/why an applicant applies to an institution, class Institution: Lots of attributes (self.quality = random.gauss(50, 10)) about the Institution and def() defining how the institution considers the applicant. class Match: this defines the interaction of the population of Applicants and Institutions, i.e. the rules of the game and returns the outcome i.e. which Applicants went to which Institutions. As of now I have been running 1 Match at a time. Which is to say generate 8000 instances of Applicant and 300 instances of Institution and then run the match Match(app_list, inst_list) and I do this with a short script. So now I need to implement my monte-carlo. By that I mean that i want to set some of the initial condition such as GPA, and Quality and basically re-run the what I descried above, (generate applicant, institutions, match them) Then save the results. So my plan way to make a new class. This class would define the Applicant characteristics "self.gpa = random.gauss(mean, SD)" and the institutions self.quality = random.gauss(mean, sd) so it would look something like this class RepeatMatch: def __int__(self, app_mean, app_sd, inst_mean, inst_sd, match_ repeat) self.app_mean = app_mean …….. self.match_repeat = match_repeat def makeApplicants(): def makeInstitutions(): def runMatches(self) # runs the match match_repeat number of times, saves results # then I calculate some characteristics of the results def ratio_dist(): # returns the Mean and sd of GPA/Quality END OF CODE Does it make sense to do it this way? Is there a better/alternative way of thinking about this. In the end I want to compare the results of repeated simulations "RepeatMatch(50,2….) Compared to RepeatMatch(50,15….)" This is way I had ask the earlier question "class attribute to initiate more classes" Thanks Vincent Davis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Accessing variables in main from functions in a module
These replies are great! Thanks to everyone who took the trouble to respond and explain. I'll need some time to digest what you say and put it to use but I'm sure your suggestions will be a huge help. On Fri, Oct 30, 2009 at 7:55 PM, Alan Gauld wrote: > "Robert Lummis" wrote > >> I want to move some functions from my "main" program file to a module >> file because the main file is getting too big for convenience. > > Good idea! > >> functions access arrays (lists of lists) that are defined and >> initialised in the main file. How do I reference the main file arrays >> from statements within the module file? > > In general you don't. You pass the data into the function. > Thats the only (sane) way to make the functions reusable, > by passing in all the data they need to do their job. Its also > the only sane way to avoid the debugging nightmare of > global variables changing under your feet due to hidden > function side effects. > > So when you move the functions, rewrite them from > > def f(...) > # stuff > to > > def f(...grid) > #stuff > return grid > > And when you call them do > > grid = mymod.f(...,grid) > > That keeps the functions independant and avoids any > mysteries about where your main function variables are > getting changed. > >> The overall program solves a game by a recursive method. > > In that case even more reason to pass the data in. Recursive > functions opertating on global variables are one of the hardest > things to debug in the programming universe, only beaten by > multiple threads modifying unsynchronised global variables! > >> and the presence of a bunch of unchanging housekeeping functions in >> the main file makes it cumbersome to read and edit. > > Yes thats one reason to move functions out. But an even better > reason is to logically partition the code into whats reusable > and what is specific to the problem. So consider whether its > really the housekeeping that wants moving or the core algorithms... > >> def functionA (row, col, x): >> grid[row][col] = >> >> where grid[] is initialised outside of any functions (i.e. in the main). >> >> So how do I write that function when I move it to a module file? I > > As above > > def functionA (row, col, x, grid): > grid[row][col] = > return grid > > and call it with > > grid = module.function(row,col,x, grid) > >> thought I read somewhere that the main routine has the name "__main__" > > A module that is being run directly has the name __main__ not a function. > >> I understand that it is best to minimize cross-file references but I >> feel it is warranted in this case. > > I doubt it. > >> Even if you think it isn't good practice I would like to understand how >> to do it (or else why it can't be done). > > You can probably do it by inspecting the call stack using the traceback > module or somesuch, but there'sd really no need. > >> Is there some other way to keep files from getting too big? > > You can use classes. You could have a Grid class with all the functions > that modify the grid as methods. Then you can create grid objects and > operate on them and each will have its own internal grid. You can then > easily move the class into a separate module as required. > > HTH, > > -- > Alan Gauld > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > > ___ > Tutor maillist - tu...@python.org > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > -- Robert Lummis ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
[Tutor] Adding Value to CSV
I have some code that is going through a number of test. When I have the line that has been read I need to add another value at the end of it, or write the information into another csv file Example of my code: for line in fh.readlines(): readline = line ipline = readline ip = ipline.split(' ')[0] split_ip = ip.split('.') if ((split_ip[0] == '"152')): ff.write(readline) totalcount +=1 I need to add another piece, how can I add another field at the end of ff.write(readline) Any assistance would be greatly appreciated. Thank You. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Adding Value to CSV
"Paras K." wrote When I have the line that has been read I need to add another value at the end of it, or write the information into another csv file If you are dealing with csv fioles you should look at using the csv module. for line in fh.readlines(): readline = line ipline = readline the readline and ipline variables are not needed. just use line! ip = ipline.split(' ')[0] split_ip = ip.split('.') if ((split_ip[0] == '"152')): you don't need the parentheses here, its not C. And you definitely don't need two sets of them! ff.write(readline) totalcount +=1 I need to add another piece, how can I add another field at the end of ff.write(line) just add it to the end of line before writing it using any of the normal string addition operations, eg: line += newfieldor line = "%s%s" % (line,newfield) 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