Re: Record seperator

2011-08-27 Thread ChasBrown
On Aug 27, 10:45 am, Roy Smith  wrote:
> In article <4e592852$0$29965$c3e8da3$54964...@news.astraweb.com>,
>  Steven D'Aprano  wrote:
>
> > open("file.txt")   # opens the file
> >  .read()           # reads the contents of the file
> >  .split("\n\n")    # splits the text on double-newlines.
>
> The biggest problem with this code is that read() slurps the entire file
> into a string.  That's fine for moderately sized files, but will fail
> (or at least be grossly inefficient) for very large files.
>
> It's always annoyed me a little that while it's easy to iterate over the
> lines of a file, it's more complicated to iterate over a file character
> by character.  You could write your own generator to do that:
>
> for c in getchar(open("file.txt")):
>    whatever
>
> def getchar(f):
>    for line in f:
>       for c in line:
>          yield c
>
> but that's annoyingly verbose (and probably not hugely efficient).

read() takes an optional size parameter; so f.read(1) is another
option...

>
> Of course, the next problem for the specific problem at hand is that
> even with an iterator over the characters of a file, split() only works
> on strings.  It would be nice to have a version of split which took an
> iterable and returned an iterator over the split components.  Maybe
> there is such a thing and I'm just missing it?

I don't know if there is such a thing; but for the OP's problem you
could read the file in chunks, e.g.:

def readgroup(f, delim, buffsize=8192):
tail=''
while True:
s = f.read(buffsize)
if not s:
yield tail
break
groups = (tail + s).split(delim)
tail = groups[-1]
for group in groups[:-1]:
yield group

for group in readgroup(open('file.txt'), '\n\n'):
# do something

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: testing if a list contains a sublist

2011-08-16 Thread ChasBrown
On Aug 16, 1:37 am, Steven D'Aprano  wrote:
> On Tue, 16 Aug 2011 04:14 pm ChasBrown wrote:
>
>
>
> > On Aug 15, 4:26 pm, Johannes  wrote:
> >> hi list,
> >> what is the best way to check if a given list (lets call it l1) is
> >> totally contained in a second list (l2)?
>
> >> for example:
> >> l1 = [1,2], l2 = [1,2,3,4,5] -> l1 is contained in l2
> >> l1 = [1,2,2,], l2 = [1,2,3,4,5] -> l1 is not contained in l2
> >> l1 = [1,2,3], l2 = [1,3,5,7] -> l1 is not contained in l2
>
> >> my problem is the second example, which makes it impossible to work with
> >> sets insteads of lists. But something like set.issubset for lists would
> >> be nice.
>
> >> greatz Johannes
>
> > My best guess:
>
> > from collections import Counter
>
> There's no reason to think that the Original Poster wants a multiset based
> solution. He asked about lists and sublists. That's a standard term, like
> substring:
>
> "12" is a substring of "01234".
> "21" and "13" are not.
>
> [1, 2] is a sublist of [0, 1, 2, 3, 4].
> [2, 1] and [1, 3] are not.
>
> Since lists are ordered, so are sublists.
>

That's reasonable; although except in the subject, the OP never uses
the term 'sublist'; instead using more ambiguous terms like
'contains', 'is totally contained', etc., with definition by limited
example. So it was a bit of a guess on my part of what was wanted.

> If the OP does want a solution that ignores order, then he needs to describe
> his problem better.

As it turns out, in another response the OP says he wants [2,1,2] to
be 'contained' by [1,2,2]. But in any case he always has sorted lists,
in which case, interestingly, the multiset approach and your more
canonical sublist approach yield the same results.

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: testing if a list contains a sublist

2011-08-16 Thread ChasBrown
On Aug 15, 11:51 pm, Laszlo Nagy  wrote:
> >> hi list,
> >> what is the best way to check if a given list (lets call it l1) is
> >> totally contained in a second list (l2)?
>
> >> for example:
> >> l1 = [1,2], l2 = [1,2,3,4,5] ->  l1 is contained in l2
> >> l1 = [1,2,2,], l2 = [1,2,3,4,5] ->  l1 is not contained in l2
> >> l1 = [1,2,3], l2 = [1,3,5,7] ->  l1 is not contained in l2
>
> >> my problem is the second example, which makes it impossible to work with
> >> sets insteads of lists. But something like set.issubset for lists would
> >> be nice.
>
> >> greatz Johannes
>
> Fastest, error-free and simplest solution is to use sets:
>
>  >>> l1 = [1,2]
>  >>> l2 = [1,2,3,4,5]
>  >>> set(l1)-set(l2)
> set([])
>  >>> set(l2)-set(l1)
> set([3, 4, 5])
>  >>>
>

This approach fails the OP's desires when

>>> l1 = [1,2,2,]
>>> l2 = [1,2,3,4,5]

The OP explicitly desires 'l2 contains l1' to be false in that case.

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: testing if a list contains a sublist

2011-08-15 Thread ChasBrown
On Aug 15, 4:26 pm, Johannes  wrote:
> hi list,
> what is the best way to check if a given list (lets call it l1) is
> totally contained in a second list (l2)?
>
> for example:
> l1 = [1,2], l2 = [1,2,3,4,5] -> l1 is contained in l2
> l1 = [1,2,2,], l2 = [1,2,3,4,5] -> l1 is not contained in l2
> l1 = [1,2,3], l2 = [1,3,5,7] -> l1 is not contained in l2
>
> my problem is the second example, which makes it impossible to work with
> sets insteads of lists. But something like set.issubset for lists would
> be nice.
>
> greatz Johannes

My best guess:

from collections import Counter

def contains(alist, sublist):
alist = Counter(alist)
for k in sublist:
try:
alist[k] -= 1
if alist[k] < 0:
return False
except KeyError:
return False
return True

'Counter' being better understood as 'Multiset'.

If m = len(alist) and n = len(sublist), looks to be roughly O(m+n).

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: testing if a list contains a sublist

2011-08-15 Thread ChasBrown
On Aug 15, 4:26 pm, Johannes  wrote:
> hi list,
> what is the best way to check if a given list (lets call it l1) is
> totally contained in a second list (l2)?
>
> for example:
> l1 = [1,2], l2 = [1,2,3,4,5] -> l1 is contained in l2
> l1 = [1,2,2,], l2 = [1,2,3,4,5] -> l1 is not contained in l2
> l1 = [1,2,3], l2 = [1,3,5,7] -> l1 is not contained in l2
>
> my problem is the second example, which makes it impossible to work with
> sets insteads of lists. But something like set.issubset for lists would
> be nice.
>
> greatz Johannes

My best guess:

from collections import Counter

def contains(alist, sublist):
alist = Counter(alist)
for k in sublist:
try:
alist[k] -= 1
if alist[k] < 0:
return False
except KeyError:
return False
return True

'Counter' being better understood as 'Multiset'.

If m = len(alist) and n = len(sublist), looks to be roughly O(m+n).

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: testing if a list contains a sublist

2011-08-15 Thread ChasBrown
On Aug 15, 4:26 pm, Johannes  wrote:
> hi list,
> what is the best way to check if a given list (lets call it l1) is
> totally contained in a second list (l2)?
>
> for example:
> l1 = [1,2], l2 = [1,2,3,4,5] -> l1 is contained in l2
> l1 = [1,2,2,], l2 = [1,2,3,4,5] -> l1 is not contained in l2
> l1 = [1,2,3], l2 = [1,3,5,7] -> l1 is not contained in l2
>
> my problem is the second example, which makes it impossible to work with
> sets insteads of lists. But something like set.issubset for lists would
> be nice.
>
> greatz Johannes

My best guess:

from collections import Counter

def contains(alist, sublist):
alist = Counter(alist)
for k in sublist:
try:
alist[k] -= 1
if alist[k] < 0:
return False
except KeyError:
return False
return True

'Counter' being better understood as 'Multiset'.

If m = len(alist) and n = len(sublist), looks to be roughly O(m+n).

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why won't this decorator work?

2011-07-02 Thread ChasBrown
On Jul 2, 11:08 am, John Salerno  wrote:
> On Jul 2, 12:33 pm, MRAB  wrote:
>
>
>
> > On 02/07/2011 17:56, John Salerno wrote:
>
> > > I thought I had finally grasped decorators, but the error I'm getting
> > > ('str' type is not callable) is confusing me.

> > > def move(roll):
> > > return 'You moved to space {0}.'.format(roll)



>
> > A decorator should return a callable.

Well, should typically return a callable, but there are exceptions...

>
> > This:
>
> >      @move
> >      def roll_die():
> >          return random.randint(1, 6)
>
> > is equivalent to this:
>
> >      def roll_die():
> >          return random.randint(1, 6)
>
> >      roll_die = move(roll_die)
>
> > You should be defining a function (a callable) and then passing it to a
> > decorator which returns a callable.
>
> > As it is, you're defining a function and then passing it to a decorator
> > which is returning a string. Strings aren't callable.
>
> But why does the documentation say "The return value of the decorator
> need not be callable"?

Well, because it need not be callable: i.e., if the return value is
not callable, that is perfectly legal. You very rarely want to return
something else, but an example of this is the @property decorator: it
returns a property object, which is not callable.

> And why, if I remove the decorator and just
> leave the two functions as if, does the call to move(roll_die()) work?
> Isn't that what the decorator syntax is essentially doing?

No; instead it's doing the similar looking but quite different

move(roll_die)()

As you wrote it, move(roll_die) returns the string 'You moved to space
.' which is not callable. You typically want
instead something like:

def move(roll):
# note that roll is a function, not a number
def wrapper():
result = roll()
print 'You moved to space {0}.'.format(result)
return result
return wrapper # which is a function

Now move returns a callable (the function 'wrapper') so move(roll_die)
is callable, and move(roll_die)() is legal.

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why won't this decorator work?

2011-07-02 Thread ChasBrown
On Jul 2, 11:08 am, John Salerno  wrote:
> On Jul 2, 12:33 pm, MRAB  wrote:
>
>
>
> > On 02/07/2011 17:56, John Salerno wrote:
>
> > > I thought I had finally grasped decorators, but the error I'm getting
> > > ('str' type is not callable) is confusing me.

> > > def move(roll):
> > > return 'You moved to space {0}.'.format(roll)



>
> > A decorator should return a callable.

Well, should typically return a callable, but there are exceptions...

>
> > This:
>
> >      @move
> >      def roll_die():
> >          return random.randint(1, 6)
>
> > is equivalent to this:
>
> >      def roll_die():
> >          return random.randint(1, 6)
>
> >      roll_die = move(roll_die)
>
> > You should be defining a function (a callable) and then passing it to a
> > decorator which returns a callable.
>
> > As it is, you're defining a function and then passing it to a decorator
> > which is returning a string. Strings aren't callable.
>
> But why does the documentation say "The return value of the decorator
> need not be callable"?

Well, because it need not be callable: i.e., if the return value is
not callable, that is perfectly legal. You very rarely want to return
something else, but an example of this is the @property decorator: it
returns a property object, which is not callable.

> And why, if I remove the decorator and just
> leave the two functions as if, does the call to move(roll_die()) work?
> Isn't that what the decorator syntax is essentially doing?

No; instead it's doing the similar looking but quite different

move(roll_die)()

As you wrote it, move(roll_die) returns the string 'You moved to space
.' which is not callable. You typically want
instead something like:

def move(roll):
# note that roll is a function, not a number
def wrapper():
result = roll()
print 'You moved to space {0}.'.format(result)
return result
return wrapper # which is a function

Now move returns a callable (the function 'wrapper') so move(roll_die)
is callable, and move(roll_die)() is legal.

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why won't this decorator work?

2011-07-02 Thread ChasBrown
On Jul 2, 11:08 am, John Salerno  wrote:
> On Jul 2, 12:33 pm, MRAB  wrote:
>
>
>
> > On 02/07/2011 17:56, John Salerno wrote:
>
> > > I thought I had finally grasped decorators, but the error I'm getting
> > > ('str' type is not callable) is confusing me.

> > > def move(roll):
> > > return 'You moved to space {0}.'.format(roll)



>
> > A decorator should return a callable.

Well, should typically return a callable, but there are exceptions...

>
> > This:
>
> >      @move
> >      def roll_die():
> >          return random.randint(1, 6)
>
> > is equivalent to this:
>
> >      def roll_die():
> >          return random.randint(1, 6)
>
> >      roll_die = move(roll_die)
>
> > You should be defining a function (a callable) and then passing it to a
> > decorator which returns a callable.
>
> > As it is, you're defining a function and then passing it to a decorator
> > which is returning a string. Strings aren't callable.
>
> But why does the documentation say "The return value of the decorator
> need not be callable"?

Well, because it need not be callable: i.e., if the return value is
not callable, that is perfectly legal. You very rarely want to return
something else, but an example of this is the @property decorator: it
returns a property object, which is not callable.

> And why, if I remove the decorator and just
> leave the two functions as if, does the call to move(roll_die()) work?
> Isn't that what the decorator syntax is essentially doing?

No; instead it's doing the similar looking but quite different

move(roll_die)()

As you wrote it, move(roll_die) returns the string 'You moved to space
.' which is not callable. You typically want
instead something like:

def move(roll):
# note that roll is a function, not a number
def wrapper():
result = roll()
print 'You moved to space {0}.'.format(result)
return result
return wrapper # which is a function

Now move returns a callable (the function 'wrapper') so move(roll_die)
is callable, and move(roll_die)() is legal.

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple instances and wrong parental links

2011-01-01 Thread ChasBrown
On Jan 1, 5:59 pm, Josh English  wrote:
> I have hit yet another wall. I am dynamically creating a class and then 
> creating instances of that class. The class relies on a second class to store 
> a list of objects. (This is simplified from the the original by a factor of 
> about 20. The real program is trying to create a Python object around an XML 
> definition object.)
>
> Here's the code:
>
> ## OPTION ONE for class: ElementList
> ### Not really a list, but a wrapper that behaves like a list
> class ElementList(object):
> def __init__(self, parent, name):
> self._parent = parent
> self._name = name
>
> def MakeWrapper(checker, _addNameAsAttribute = False ):
>
> ## OPTION TWO for class: ElementList
> class Wrap(object):
>
> ## OPTION THREE for class: Elementlist
>
> def __init__(self, name):
> self._name = name
> setattr(Wrap, 'stuff', ElementList(self, 'test'))
>
> Wrap.__name__= checker.title()
>
> return Wrap
>
> if __name__ == '__main__':
>
> Dude = MakeWrapper('Dude')
> print Dude
> d1 = Dude('Josh')
> print d1, d1.stuff
>
> # creating the second instance changes the behavior of the subclass
> d2 = Dude('Ben')
> print d2, d2.stuff
> print d1.stuff._parent
> print d2.stuff._parent
>
> #creating a third instance changes the behavior of all the subclasses
> d3 = Dude('David')
> print d3, d3.stuff
> print d1.stuff._parent, d2.stuff._parent, d3.stuff._parent
>
> ## END CODE
>
> And here is the output:
>
>
>
> 
> <__main__.Dude object at 0x00DFB930> <__main__.ElementList object at 
> 0x00DFB950>
> <__main__.Dude object at 0x00DFB730> <__main__.ElementList object at 
> 0x00DFB770>
> <__main__.Dude object at 0x00DFB730>
> <__main__.Dude object at 0x00DFB730>
> <__main__.Dude object at 0x00DFB870> <__main__.ElementList object at 
> 0x00DFB9B0>
> <__main__.Dude object at 0x00DFB870> <__main__.Dude object at 0x00DFB870> 
> <__main__.Dude object at 0x00DFB870>
>
> The 'stuff' attribute is an ElementList object linked back to the parent 
> instance, but every time I create an instance, every instance's 'stuff' links 
> back to the last instance created.
>

If every instance's  is the same, one guesses that the
 has a class scope, rather than an instance scope.

> I'm not sure why this is happening, or how to prevent it.
>

It's perfectly predictable; to understand what is happening, compare:

>>> def foo():
class Bar(object):
def __init__(self):
setattr(Bar, 'stuff', {})
return Bar

>>> Dude = foo()
>>> a = Dude()
>>> b = Dude()
>>> a.stuff['foo'] = 2
>>> b.stuff
{'foo': 2}
>>> c = Dude()
>>> a.stuff
{}

with the behavior (which I think you expected) of:

>>> def foo():
class Bar(object):
def __init__(self):
setattr(self, 'stuff', {})
return Bar

>>> Dude = foo()
>>> a = Dude()
>>> b = Dude()
>>> a.stuff['foo'] = 2
>>> b.stuff
{}
>>> c = Dude()
>>> a.stuff
{'foo': 2}

Cheers - Chas
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How can a function find the function that called it?

2010-12-24 Thread ChasBrown
On Dec 24, 8:24 am, kj  wrote:
> I want to implement a frozen and ordered dict.
>
> I thought I'd implement it as a subclass of collections.OrderedDict
> that prohibits all modifications to the dictionary after it has
> been initialized.
>
> In particular, calling this frozen subclass's update method should,
> in general, trigger an exception ("object is not mutable").
>
> But OrderedDict's functionality *requires* that its __init__ be
> run, and this __init__, in turn, does part of its initialization
> by calling the update method.
>

Rather than trying to identify the caller, I'd do something like:

class FrozenODict(OrderedDict):

def __init__(self, *args, **kwargs):
OrderedDict.__init__(self, *args, **kwargs)
self.update = self._update # init is complete, so override
   # update method for this instance

def _update(self, dict2):
raise Exception("object is immutable!!")

After the __init__, calls to the instance's 'update' function will be
mapped to _update. It's essentially overriding the inherited function
on the fly.

Cheers - Chas

-- 
http://mail.python.org/mailman/listinfo/python-list