Re: Why won't this decorator work?
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?
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?
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: testing if a list contains a sublist
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
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
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
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
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: Record seperator
On Aug 27, 10:45 am, Roy Smith wrote: > In article <[email protected]>, > 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: How can a function find the function that called it?
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
Re: Multiple instances and wrong parental links
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
