Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.002 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; '*is*': 0.09; 'function:': 0.09; 'global,': 0.09; 'imported': 0.09; 'omit': 0.09; 'overwrite': 0.09; 'whichever': 0.09; 'runs': 0.10; 'cc:addr :python-list': 0.11; 'def': 0.12; '"code': 0.16; 'caching': 0.16; 'called,': 0.16; 'called.': 0.16; 'deferred': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'func():': 0.16; 'globals': 0.16; 'imports': 0.16; "module's": 0.16; 'subject: \n ': 0.16; 'subject:bound': 0.16; 'variable.': 0.16; 'variables),': 0.16; 'wrote:': 0.18; 'code.': 0.18; 'looked': 0.18; 'all,': 0.19; 'bit': 0.19; 'module': 0.19; 'finished': 0.19; 'not,': 0.20; '>>>': 0.22; 'example': 0.22; 'import': 0.22; 'cc:addr:python.org': 0.22; 'circular': 0.24; 'instance,': 0.24; 'math': 0.24; '(or': 0.24; 'cc:2**0': 0.24; 'sort': 0.25; "i've": 0.25; 'second': 0.26; 'gets': 0.27; 'header :In-Reply-To:1': 0.27; 'idea': 0.28; 'point': 0.28; 'function': 0.29; 'correct': 0.29; 'chris': 0.29; "doesn't": 0.30; 'dec': 0.30; 'message-id:@mail.gmail.com': 0.30; 'work.': 0.31; 'code': 0.31; 'comments': 0.31; 'too.': 0.31; "d'aprano": 0.31; 'names.': 0.31; 'steven': 0.31; 'subject:About': 0.31; 'subject:what': 0.31; 'anyone': 0.31; 'this.': 0.32; 'fri,': 0.33; 'skip:d 20': 0.34; "i'd": 0.34; 'could': 0.34; 'subject: (': 0.35; 'something': 0.35; 'but': 0.35; 'received:google.com': 0.35; 'module.': 0.36; 'doing': 0.36; 'example,': 0.37; 'so,': 0.37; 'two': 0.37; 'sometimes': 0.38; 'pm,': 0.38; 'anything': 0.39; 'does': 0.39; 'either': 0.39; 'called': 0.40; 'ensure': 0.60; 'liked': 0.60; 'making': 0.63; 'name': 0.63; 'real': 0.63; 'happen': 0.63; 'subject:The': 0.64; 'more': 0.64; 'different': 0.65; 'production': 0.68; 'risk': 0.72; 'unusual': 0.74; 'confusing': 0.84; 'object:': 0.84; 'subject:gets': 0.84; 'to:none': 0.92; 'imagine': 0.93; 'serious': 0.97 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=lOjq7stROvBSH1gewXizCJMVL2K4GTc35aiUufCvDzE=; b=0qwx2yhwfdeuqE+Htjj98JlyoVBpnvhLihoBI/jxJAfXHhX1YKcuiQEBjP4iWVAz8G N8MkhGHiB+RhfTo3i1fJFtf6uT5bkY39qhmLtKVcoh7637kwTjeLlfdfbkV986+Ifbd0 Mhcbf1Al1jr3iWdgRGcgtw9xQY83jq0gx4Bhdepn2HjaqOEdpA8uyZu/D4KzgvRd3ZsA mqogaMCLEpLEk8NsJbbBCAEHxex1C3zwCzAH26gkzQSZdV0FQ518Cx4crqLDzaHcjVnx TIIZxgv468MvvqKZwISOSK5oq1W4APcxBHqRooYYAZ4qPweroPP9k1N4TGH/i6YVkPD9 VpdA== MIME-Version: 1.0 X-Received: by 10.107.17.79 with SMTP id z76mr14257842ioi.27.1417783357115; Fri, 05 Dec 2014 04:42:37 -0800 (PST) In-Reply-To: <5481a493$0$13012$c3e8da3$5496439d@news.astraweb.com> References: <548113f3$0$13003$c3e8da3$5496439d@news.astraweb.com> <548180ae$0$13007$c3e8da3$5496439d@news.astraweb.com> <5481a493$0$13012$c3e8da3$5496439d@news.astraweb.com> Date: Fri, 5 Dec 2014 23:42:37 +1100 Subject: Re: The binding operator, and what gets bound to what (was: About Modifying Globals) From: Chris Angelico Cc: "python-list@python.org" 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: 59 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1417783360 news.xs4all.nl 2964 [2001:888:2000:d::a6]:45810 X-Complaints-To: abuse@xs4all.nl Path: csiph.com!usenet.pasdenom.info!bete-des-vosges.org!feed.ac-versailles.fr!nerim.net!novso.com!newsfeed.xs4all.nl!newsfeed4a.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Xref: csiph.com comp.lang.python:82001 On Fri, Dec 5, 2014 at 11:26 PM, Steven D'Aprano wrote: > Chris Angelico wrote: > >>> def func(): >>> global math >>> import math >> >> When would you actually *want* this, though? Given that 'import' >> already caches, there's not much point caching globally, and the idea >> that a function could cause a module-level import to happen is pretty >> weird! > > That's one way of dealing with circular imports. That way the problematic > import is deferred until the function is called, which hopefully is after > both modules have finished initialising their global names. And by making > the imported name a global, you don't have to bother writing "import math" > in every single function. You just need to ensure your initialisation > function is called before doing any real work. Ah. I've never liked circular imports at all, so I've never actually looked into ways of dealing with them. So basically, func() is a sort of "second phase initialization" routine, to be called before any of the module's real work gets called. > Oooh! That's nice too! > > >> So, for instance, if you need a JavaScript executor, you might support >> several different runtimes, and allow one to be selected like this. >> But this would be serious code smell. > > No more than any other global variable. Just because something is unusual > doesn't make it harmful. If you have globals (constants, or variables), you > might put their initialisation code into a function: That's why I said "code smell". Imagine the usage of a module like that: import module module.use_foo() # What happens if you omit this line? module.do_stuff() This is true of your circular imports example, too. Anything that requires a two-step initialization runs the risk of someone either forgetting, or having two imports in different modules and having them out of sync. (With the code example I gave, whichever one is imported second will "stick", because the use_* functions overwrite each other.) So it's going to be a bit confusing to people using the module. It might be better to have a deliberately-instantiated object: import module stuff_doer = module.use_foo() stuff_doer.do_stuff() It also might not, of course, which is the point of code smell - it *is* sometimes correct - but I'd want to see some justifying comments (or docstring) if anyone does this in production code. ChrisA