Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!backfill.erje.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'python,': 0.02; 'else:': 0.03; 'syntax': 0.04; 'elif': 0.05; 'class,': 0.07; 'method.': 0.07; 'callback': 0.09; 'classes.': 0.09; 'constructor': 0.09; 'data:': 0.09; 'front,': 0.09; 'function,': 0.09; 'method,': 0.09; 'url:blog': 0.10; 'python': 0.11; 'def': 0.12; 'mostly': 0.14; 'command)': 0.16; 'data)': 0.16; 'function;': 0.16; 'lambda': 0.16; 'lambda:': 0.16; 'limited)': 0.16; 'mine.': 0.16; 'specifying': 0.16; 'subject:object': 0.16; 'subject:simple': 0.16; 'subject:type': 0.16; 'java,': 0.16; 'language': 0.16; 'wrote:': 0.18; 'command': 0.22; '>>>': 0.22; 'aug': 0.22; "aren't": 0.24; 'class.': 0.26; 'this:': 0.26; 'header:In-Reply- To:1': 0.27; 'point': 0.28; 'function': 0.29; 'raise': 0.29; 'message-id:@mail.gmail.com': 0.30; "i'm": 0.30; 'anonymous': 0.31; "d'aprano": 0.31; 'skip:q 20': 0.31; 'steven': 0.31; 'class': 0.32; 'probably': 0.32; 'front': 0.32; 'interface': 0.32; 'implemented': 0.33; 'totally': 0.33; 'used,': 0.33; 'third': 0.33; 'actual': 0.34; 'skip:_ 10': 0.34; 'could': 0.34; 'classes': 0.35; 'case,': 0.35; 'received:google.com': 0.35; 'really': 0.36; 'scheme': 0.36; 'done': 0.36; 'url:org': 0.36; 'experience,': 0.37; 'project': 0.37; 'easily': 0.37; 'being': 0.38; 'implement': 0.38; 'to:addr:python-list': 0.38; 'pm,': 0.38; 'subject:" ': 0.39; 'to:addr:python.org': 0.39; 'enough': 0.39; 'back': 0.62; 'name': 0.63; 'url:p': 0.64; 'provide': 0.64; 'more': 0.64; 'linked': 0.65; 'talking': 0.65; 'here': 0.66; 'to,': 0.72; 'as:': 0.81; 'localized': 0.84; 'object:': 0.84; 'write:': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=nM2/PDdSLUzmyGNiRgOu63nl0lXRq+ImUq/ZEWjNh8w=; b=vLCRZtJGdjetTpM0pmh9t+9/ESNlUL0bdkSIezpX1Y6FwEWPlK+8YOuaQ5VJ8GccGs pu16yojcPzfvuYL9ql9PEjk2aaIPT+ZpIKYYXWnhyueBOTUTJA+md6SSmAex4C+Y76iB r0EEgxB3KV+Nr3cEZB6Db+0VH9spc/JkBuIg/JdZei2v/EhCv0ouS/rSRH2cjyhjOgLT jisGuZbBqnCCS2vMEXs9K7xWh3gVDASe2FY7b5HQg+eg/XHm+HRgFdeQnhw9pgPavSPz /yj9noZtP3roYW3voF36VweWZrX5Jg7yDR95kwJFXg8BHh5ld2yxswZmdS0ZXOPEu5b0 5oQQ== X-Received: by 10.70.128.137 with SMTP id no9mr278833pdb.143.1407134533962; Sun, 03 Aug 2014 23:42:13 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <8738dclslo.fsf@elektro.pacujo.net> References: <7ef67ccc-3fc3-47dd-b858-09ef3b57a497@googlegroups.com> <87r40zmkhr.fsf@elektro.pacujo.net> <53dd0717$0$29973$c3e8da3$5496439d@news.astraweb.com> <70e5f2f1-661f-40f2-bb7a-76e569c4d092@googlegroups.com> <1407057464.64980.YahooMailNeo@web163806.mail.gq1.yahoo.com> <1407063072.46317.YahooMailNeo@web163803.mail.gq1.yahoo.com> <87wqaplj8h.fsf@elektro.pacujo.net> <53ded02e$0$29980$c3e8da3$5496439d@news.astraweb.com> <8738dclslo.fsf@elektro.pacujo.net> From: Ian Kelly Date: Mon, 4 Aug 2014 00:41:32 -0600 Subject: Re: Correct type for a simple "bag of attributes" namespace object To: Python Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 99 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1407134543 news.xs4all.nl 2942 [2001:888:2000:d::a6]:49016 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:75665 On Sun, Aug 3, 2014 at 11:41 PM, Marko Rauhamaa wrote: > Steven D'Aprano : > And I'm talking about a third kind: object-based. It is in active > (albeit limited) use in scheme: . I'm > currently using the principle in a project of mine. > > In Java, you use anonymous classes for the same thing. In Python, you > can think of the principle as one-time classes. So instead of writing: In my experience, 99% of the time when anonymous classes are used, they only contain one method. That's because they're not really being used to implement some interface abstractly; they mostly exist to provide a means of specifying a callback function in a language where functions aren't first-class. > > class A: > def __init__(self, x, y, z): > self.x = x > self.d = y * y + z * z > > def f(self): > return self.x - self.d > > you write: > > def A(x, y, z): > d = y * y + z * z > > class Anonymous: > def f(self): > return x - d > > return Anonymous() And it's the same thing here. This isn't an interface. It's a function, so just return a function and be done with it. And in the rare event that you actually mean to implement more than one method, then you have enough functionality localized that it's probably worthwhile to just name it and make it an actual class. > Now, if you always did this, you would notice that classes are > unnecessary clutter and would call for syntax like this: > > def A(x, y, z): > d = y * y + z * z > return object: > def f(): > return x - d The presence of "object" here feels totally unnecessary to me. If the point is to avoid having a class, then why create a class? In this case you could easily just return a function. To take a more complex case, say the Scheme make-queue constructor that you linked to, you could still just return a function; the same could be implemented in Python 3 as: def make_queue(): front = [] back = [] def queue_command(command, data=None): def exchange(): nonlocal front, back front = back; front.reverse() back = [] if command == 'push': back.append(data) elif command == 'pop': if not front: exchange() return front.pop() elif command == 'peek': if not front: exchange() return front[-1] elif command == 'show': return str(list(reversed(front)) + back) else: raise ValueError('Illegal command to queue object ' + command) queue_command.push = lambda data: queue_command('push', data) queue_command.pop = lambda: queue_command('pop') queue_command.peek = lambda: queue_command('peek') return queue_command >>> queue = make_queue() >>> queue.push(1) >>> queue.push(2) >>> queue.pop() 1 >>> queue.push(3) >>> queue.push(4) >>> queue.pop() 2 >>> queue.peek() 3 >>> queue.pop() 3 >>> queue.pop() 4