Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
BigRedDot
Mar 6, 2008

Haystack posted:

Yeah, this one gets a lot of people. Basically, when you assign to a variable anywhere within a scope (such as the one a function creates), it overwrites any outer variable, regardless of whether or not the logical flow assigns anything to the variable. It's generally considered a flaw in the language, and python 3 added a keyword that lets you work around it.

Who considers this a flaw? The alternative is that whether or not a statement references a local or global reference depends on whether or not some condition happens to succeed or fail. That would be pretty impossible to reason about in any sensible way and would lead to all manner of subtle bugs.

I'm also wondering what keyword you are referring to. There was nonlocal that was added but that's really only useful in closures.

Adbot
ADBOT LOVES YOU

evensevenone
May 12, 2001
Glass is a solid.

BigRedDot posted:

Who considers this a flaw? The alternative is that whether or not a statement references a local or global reference depends on whether or not some condition happens to succeed or fail. That would be pretty impossible to reason about in any sensible way and would lead to all manner of subtle bugs.

I think what most people expect, thinking that python is an interpreted language, is that resolution would occur line-by-line. If the local has been defined yet, then it's local. If it's not, then you start going up and looking for a global. If you can't find it anywhere, then you throw an error. By the way, guess what this produces.

Python code:
foo = 'bar'
def printLocals():
    print locals()
    foo = 'foo'
    print locals()

Dominoes
Sep 20, 2007

evensevenone posted:

I think what most people expect, thinking that python is an interpreted language, is that resolution would occur line-by-line. If the local has been defined yet, then it's local. If it's not, then you start going up and looking for a global. If you can't find it anywhere, then you throw an error. By the way, guess what this produces.

Python code:
foo = 'bar'
def printLocals():
    print locals()
    foo = 'foo'
    print locals()
Weird; that doesn't seem consistent, which I think is your point. The first print doesn't recognize 'foo' as a local variable, showing it working sequentially, yet the 'foo = ' expression existing anywhere in the function can cause UnboundLocalErrors.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

The best solution is no more globals! :p

Emacs Headroom
Aug 2, 2003

Thermopyle posted:

The best solution is no more globals! :p

Would this stuff also apply to nested scopes that weren't global (e.g. closures)?

edit: yeah looks like
Python code:
In [4]: def newtest():
   ...:     foo = 'bar'
   ...:     def printfoo():
   ...:         print foo
   ...:     def printfoo2():
   ...:         if False:
   ...:             foo = 'foo'
   ...:         print foo
   ...:     printfoo()
   ...:     printfoo2()
   ...: 

In [5]: newtest()
bar
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-5-559acc358b60> in <module>()
----> 1 newtest()

<ipython-input-4-31d80a8f4fd3> in newtest()
      8         print foo
      9     printfoo()
---> 10     printfoo2()

<ipython-input-4-31d80a8f4fd3> in printfoo2()
      6         if False:
      7             foo = 'foo'
----> 8         print foo
      9     printfoo()
     10     printfoo2()

UnboundLocalError: local variable 'foo' referenced before assignment

edit2, for completeness
Python code:
In [6]: def newtest():
    foo = 'bar'
    def printfoo():
        print foo
    def printfoo2():
        if False:
            foo = 'foo'
        print foo
    return printfoo, printfoo2
   ...: 

In [7]: a, b = newtest()

In [8]: a()
bar

In [9]: b()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-9-9c619ddbd09b> in <module>()
----> 1 b()

<ipython-input-6-1ff4bef666ff> in printfoo2()
      6         if False:
      7             foo = 'foo'
----> 8         print foo
      9     return printfoo, printfoo2

UnboundLocalError: local variable 'foo' referenced before assignment

In [10]: a()
bar

Emacs Headroom fucked around with this message at 18:45 on Jul 21, 2013

Dominoes
Sep 20, 2007

Mr. Wynand posted:

That's kind of weird for HTTP.

Does the response have a "Transfer-Encoding: Chunked" header? I guess they could be sending down a coherent blob of json each chunk, but how do you tell it to end?

Oops - was using the wrong endpoint. There is indeed a "Transfer-Encoding: Chunked" header in the streaming API. I'm still a bit unclear how to use it - I'm trying r.iter_lines() per the documents. There's also a section on chunked data, referring passing a generator function as the "data" property. I can't figure out how to get data from the open HTTP socket, but it seems like the program can't continue with the request open, so perhaps streaming requires a separate thread.

Dominoes fucked around with this message at 19:04 on Jul 21, 2013

evensevenone
May 12, 2001
Glass is a solid.

Thermopyle posted:

The best solution is no more globals! :p

Well, the same thing happens with all names. The issue that brought this up was actually a module name that had the same name as a local variable in a later part of the function.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

evensevenone posted:

Well, the same thing happens with all names. The issue that brought this up was actually a module name that had the same name as a local variable in a later part of the function.

Yeah, I got you.

In other news, PyCharm 3.0 EAP is out and a notable feature is more extensive SQLAlchemy support!

BigRedDot
Mar 6, 2008

evensevenone posted:

I think what most people expect, thinking that python is an interpreted language, is that resolution would occur line-by-line. If the local has been defined yet, then it's local. If it's not, then you start going up and looking for a global. If you can't find it anywhere, then you throw an error.

I agree that's what a person might expect at first blush. I think after actually giving it any amount of thought whatsoever they would conclude that that would be a terrible idea in practice.

BigRedDot fucked around with this message at 00:59 on Jul 22, 2013

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug

Moddington posted:

Plus, you taught me you can use tuples in function argument definitions. Don't know how I missed that handy little bit of syntax.
Python code:
    def add(self, n, (row, col)):
        if self.in_grid((row, col)):
            n.append(self.grid[row][col])
Do not use this syntax. It is a language mistake that was removed in current versions of Python.

Telarra
Oct 9, 2012

Lysidas posted:

Do not use this syntax. It is a language mistake that was removed in current versions of Python.

Yeah, I found that out today when I tried to use it. Guess that's why I missed it before.

QuarkJets
Sep 8, 2008

Thermopyle posted:

The best solution is no more globals! :p

I agree with this. Whenever you think you need a global, there's actually a solution that doesn't use globals and that is also probably easier to understand

evensevenone
May 12, 2001
Glass is a solid.

QuarkJets posted:

I agree with this. Whenever you think you need a global, there's actually a solution that doesn't use globals and that is also probably easier to understand

The same resolution scheme applies to everything: imported modules, classes, bare functions, etc. Something has to go in the global namespace and it has to have a name.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Is there a reason why this isn't allowed? (Two sequences to unpack in a call)

I mean, it's clear why it isn't allowed in the def statement argument list. It wouldn't be meaningful to have two starred arguments there. But I think it's obvious what the below "should" do.

code:
def myFunction (*args):
   pass

myFunction(1, *(2, 3), *(4, 5))
Edit: In case it's *not* obvious, I think it "should" work out as if it said

code:
myFunction(1, 2, 3, 4, 5)
In case it gets brought up, I think it would work for ** arguments too. If later ** arguments contain same keywords then it would work like the dictionary update() method (the matching keys from the previous ** arguments get overwritten).

Hammerite fucked around with this message at 09:41 on Jul 22, 2013

tef
May 30, 2004

-> some l-system crap ->
http://www.python.org/dev/peps/pep-0448/ :3:

Mrs. Wynand
Nov 23, 2002

DLT 4EVA

Dominoes posted:

Oops - was using the wrong endpoint. There is indeed a "Transfer-Encoding: Chunked" header in the streaming API. I'm still a bit unclear how to use it - I'm trying r.iter_lines() per the documents. There's also a section on chunked data, referring passing a generator function as the "data" property. I can't figure out how to get data from the open HTTP socket, but it seems like the program can't continue with the request open, so perhaps streaming requires a separate thread.

So is it a blob of coherent json in each chunk? Does it just keep going until you forcefully close the connection?

Dominoes
Sep 20, 2007

Mr. Wynand posted:

So is it a blob of coherent json in each chunk? Does it just keep going until you forcefully close the connection?

2nd question - apparently yes. From the TradeKing website:

quote:

The socket must stay open!
The way HTTP streaming works is by opening an HTTP socket to our servers and never closing it, until a) the server goes down or disconnects you, or b) you disconnect the session yourself. By doing this, you can consistently read the data being sent through the socket. It is akin to making a request to an infinite web page -- that data continues to flow to you as long as you are still listening.

I'm still trying to figure out how to make it work; when using the correct (streaming) endpoint, I can no longer receive any useful data.

Python code:
s = requests.Session()
def streaming(symbols):
    url = 'https://stream.tradeking.com/v1/market/quotes.json'
    payload = {'symbols': ','.join(symbols)}
    return s.get(url, params=payload, stream=True)

r = streaming(['AAPL', 'GOOG'])
print(r.headers)
The printed headers: {'connection': 'keep-alive', 'content-type': 'application/json', 'x-powered-by': 'Express', 'transfer-encoding': 'chunked'}

If I only run that, the code stops after printing the headers. When i run 'print(r.json())', I don't get any output (except for output before that line), and the console window stays up with a flashing cursor, indicating it's doing something, indefinitely. The Requests docs suggest running this for streaming:

Python code:
for line in r.iter_lines():
    print(line)
This prints b'{"status":"connected"}{"status":disconnected"}', and the code stops. If I use line.json() instead, I get AttributeError: 'bytes' object has no attribute 'json'. The Chunked Data section of the requests doc shows using a generator function as the 'data' field, but I have no idea how to implement it; the example is not helpful. I barely understand generator functions as-is. Given that this API can work with get and post requests, and the 'data' field is used by Requests for the attributes to pass in the request (ie 'AAPL', 'GOOG'), which the get equivolent for is 'params', I'm even more confused.


Unrelated: Is there an easy way to play MIDI files in Python? PyAudio and PyGame are good for playing WAVs or other sampled input, and PyGame has many tools for creating MIDI or sending it to/receiving it from external devices, but has no obvious way to play midi files.

Dominoes fucked around with this message at 22:36 on Jul 22, 2013

Houston Rockets
Apr 15, 2006

Can you post your latest code in a gist? Or PM me an API key I can test with?

Dominoes
Sep 20, 2007

Houston Rockets posted:

Can you post your latest code in a gist? Or PM me an API key I can test with?
I can't figure out GIST atm. (Smashing "Create Public Gist" with no results) Here's a link to the file. It's an API-specific module of a larger stock analysis program I'm working on. Most of the code isn't directly relevant; the bit that is is similar to the code snippets I've posted.

I'm not comfortable giving out my current keys, since they're linked to my brokerage account (it buys/sells stocks, performs requests with the account balances etc), but I may be able to get user keys.

Dominoes fucked around with this message at 23:35 on Jul 22, 2013

duck monster
Dec 15, 2004

QuarkJets posted:

I would like to create a GUI with PyQt that displays a 2D numpy array. Is this relatively straightforward? Is it better to convert the image to a QPixMap or a QImage? Or is it better to try to embed matplotlib into my PyQt GUI? I'm creating a slider so that the displayed image can be switched rapidly, so I was imagining that refreshing matplotlib over and over might be suboptimal, but maybe not?

I'm still fond of Kivy for doing GUIs. Its all bleeding edge stuff, but its cross plaform as hell, and very pretty.

Personally I'd be trying to prerender those images as much as possible,, and just load up a background buffer with the next (and previous if the slider goes both ways) images so you can just blit them across.

edit: If these datasets are really big, you might even want to consider setting up your bitmaps using something like cython with static typing which can win you some pretty huge speed-ups if done right.

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

Hammerite posted:

Is there a reason why this isn't allowed? (Two sequences to unpack in a call)

I mean, it's clear why it isn't allowed in the def statement argument list. It wouldn't be meaningful to have two starred arguments there. But I think it's obvious what the below "should" do.

code:
def myFunction (*args):
   pass

myFunction(1, *(2, 3), *(4, 5))
Edit: In case it's *not* obvious, I think it "should" work out as if it said

code:
myFunction(1, 2, 3, 4, 5)
In case it gets brought up, I think it would work for ** arguments too. If later ** arguments contain same keywords then it would work like the dictionary update() method (the matching keys from the previous ** arguments get overwritten).

I was just wondering the other day if something like this would be too crazy:
Python code:
[n
 if (n % 2) == 0
 else *range(n)
 for n in range(6)] # [0, 1, 0, 2, 0, 1, 2, 4, 0, 1, 2, 3, 4]
I'm ready for PEP448 :getin:

Jose Cuervo
Aug 25, 2004
What is the difference between dict.values() and dict.itervalues()?

For example in the following code snippets as far as I can tell they produce the same output.
Python code:
dict= {'six':6, 'seven':7, 'eight':8}

for f in dict.values():
    print f
and
Python code:
dict= {'six':6, 'seven':7, 'eight':8}

for f in dict.itervalues():
    print f
So when would (or should) I use one over the other?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Jose Cuervo posted:

What is the difference between dict.values() and dict.itervalues()?

For example in the following code snippets as far as I can tell they produce the same output.
Python code:
dict= {'six':6, 'seven':7, 'eight':8}

for f in dict.values():
    print f
and
Python code:
dict= {'six':6, 'seven':7, 'eight':8}

for f in dict.itervalues():
    print f
So when would (or should) I use one over the other?

values() returns a list, itervalues() returns an iterator.

If after reading that, you have more questions...ask away!

tef
May 30, 2004

-> some l-system crap ->
Use itervalues(). It uses less memory and it is generally quicker.

Posting Principle
Dec 10, 2011

by Ralp
If you ever get to use Python 3.x, the normal keys/values/items methods return iterators rather than lists.

tef
May 30, 2004

-> some l-system crap ->
In Py3, they're called views. http://www.python.org/dev/peps/pep-3106/

quote:

There are (at least) two ways to accomplish this. The original plan was to simply let .keys(), .values() and .items() return an iterator, i.e. exactly what iterkeys(), itervalues() and iteritems() return in Python 2.x. However, the Java Collections Framework [1] suggests that a better solution is possible: the methods return objects with set behavior (for .keys() and .items()) or multiset (== bag) behavior (for .values()) that do not contain copies of the keys, values or items, but rather reference the underlying dict and pull their values out of the dict as needed.

Posting Principle
Dec 10, 2011

by Ralp
I should have remembered the distinction between views and iterators because I literally used the set operations to find the intersection of two dicts yesterday. Thank you for the excellent link as usual.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
2.7 also has viewkeys() etc. for if you want the python 3 semantics.

Count Thrashula
Jun 1, 2003

Death is nothing compared to vindication.
Buglord
I'm working on a Curses-based program, which is my first GUI-based Python application.

There are elements on the screen that I want to update in real-time (by means of a function that updates the .addstr()'s and .refresh()'es the screen/window). The problem is, I want to be able to update in real-time, but still have the option of key entry (using [screen].getch() ). When I do that, obviously it stops at the .getch(), and I have to press a key in order to refresh the info on the screen.

How can I get around that?

edit-- this is my main loop as it stands. I don't have hardly any functionality built in yet as I want to get over this one hurdle first.

Python code:
def main(stdscr):
    ''' Screen inits and refresh '''
    global screen
    screen = stdscr.subwin(23, 79, 0, 0)
    screen.hline(2, 1, curses.ACS_HLINE, 77)
    screen.box()
    screen.refresh()
    ''' Main loop to get info from API, draw it, and quit if 'Q' key is pressed '''
    while True:
        get_sab_status()
        draw_menu()
        draw_data()
        char_x = screen.getch()
        if char_x == ord('q'): break

Count Thrashula fucked around with this message at 22:42 on Jul 23, 2013

The March Hare
Oct 15, 2006

Je rêve d'un
Wayne's World 3
Buglord
Figure I'll ask in here to see if this is possible in Python. Is there anything that will allow me to make a really simple tray icon + menu for a small python script on osx?

thorf
Jun 26, 2013

The March Hare posted:

Is there anything that will allow me to make a really simple tray icon + menu for a small python script on osx?

Yes. In wxPython 2.9.2 or higher, there's a class called TaskBarIcon.

More: http://wxpython.org/docs/api/wx.TaskBarIcon-class.html

Alligator
Jun 10, 2009

LOCK AND LOAF

QPZIL posted:

I'm working on a Curses-based program, which is my first GUI-based Python application.

There are elements on the screen that I want to update in real-time (by means of a function that updates the .addstr()'s and .refresh()'es the screen/window). The problem is, I want to be able to update in real-time, but still have the option of key entry (using [screen].getch() ). When I do that, obviously it stops at the .getch(), and I have to press a key in order to refresh the info on the screen.

How can I get around that?

edit-- this is my main loop as it stands. I don't have hardly any functionality built in yet as I want to get over this one hurdle first.

[snip]
You can set screen.nodelay(1) to make getch non-blocking, so it'll return instantly. If there's no input it returns -1 so you need to check for that.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
How bad/good/incomprehensible is this, as a practice?

Python code:
def do_a_thing (arg, another_arg, return_type = set):
    return_value = []
    # some stuff happens; objects are appended to return_value; murder
    # and intrigue; the hero falls in love and has his heart broken
    return return_value if return_type == list else return_type(return_value)
Basically I made two related functions (well, three actually, but two will do). Each can in principle be called by a user of the module. Each needs to return a collection of things which is in principle unordered, so the return type is a set. But hang on, one of the functions is designed to wrap the other and do some more work, and if the "inside" function returns a set then I just have to wrap the call to it in list() anyway, and then I'm basically doing list(set(thing)) which is silly. So it would be good if I had another version of that function that returns a list instead of a se - wait a minute, if I were to...

(NB. The collections output by the functions are without duplicates irrespective of whether sets are involved at any point)

BigRedDot
Mar 6, 2008

Hammerite posted:

How bad/good/incomprehensible is this, as a practice?

Python code:
def do_a_thing (arg, another_arg, return_type = set):
    return_value = []
    # some stuff happens; objects are appended to return_value; murder
    # and intrigue; the hero falls in love and has his heart broken
    return return_value if return_type == list else return_type(return_value)
Basically I made two related functions (well, three actually, but two will do). Each can in principle be called by a user of the module. Each needs to return a collection of things which is in principle unordered, so the return type is a set. But hang on, one of the functions is designed to wrap the other and do some more work, and if the "inside" function returns a set then I just have to wrap the call to it in list() anyway, and then I'm basically doing list(set(thing)) which is silly. So it would be good if I had another version of that function that returns a list instead of a se - wait a minute, if I were to...

(NB. The collections output by the functions are without duplicates irrespective of whether sets are involved at any point)

Why is list(set(thing)) silly? It is simple, short, and only applies in the one place where a list is needed. By contrast this solution mucks up the interface to a function with parameters that have nothing to with the function or its usual use. And worse now you are doing set(list(thing)) all the time, presumably making your common case slower. If you were trying to do this for performance reasons to avoid the copy, you've made it worse. :) Better to create a set, and only convert it to a list when you need a list if that is not the common case. Or else start off by creating an empty return_type at the start and filling it up instead of doing wholesale conversions, or better just have different functions that return different things. That's actually my biggest objection: that the return type can vary. This isn't as terrible as the awful "return a collection except if there is only one thing return the thing" transgression because it's explicitly switching on a parameter and can be documented, but I would not personally write code like this normally.

AlexG
Jul 15, 2004
If you can't solve a problem with gaffer tape, it's probably insoluble anyway.

Hammerite posted:

How bad/good/incomprehensible is this, as a practice?

Python code:
def do_a_thing (arg, another_arg, return_type = set):
    return_value = []
    # some stuff happens; objects are appended to return_value; murder
    # and intrigue; the hero falls in love and has his heart broken
    return return_value if return_type == list else return_type(return_value)
Basically I made two related functions (well, three actually, but two will do). Each can in principle be called by a user of the module. Each needs to return a collection of things which is in principle unordered, so the return type is a set. But hang on, one of the functions is designed to wrap the other and do some more work, and if the "inside" function returns a set then I just have to wrap the call to it in list() anyway, and then I'm basically doing list(set(thing)) which is silly. So it would be good if I had another version of that function that returns a list instead of a se - wait a minute, if I were to...

(NB. The collections output by the functions are without duplicates irrespective of whether sets are involved at any point)

My preference would be to see if you can turn do_a_thing into a generator. Then your code or user code can easily make lists or sets or just iterate over the things.

FoiledAgain
May 6, 2007

edit: Here's the lesson kids - never forget to .grid() your widgets!

FoiledAgain fucked around with this message at 22:03 on Jul 24, 2013

QuarkJets
Sep 8, 2008

General advice in the thread has been to abandon TKinter and go with wxPython or PyQt. I'm not really familiar with TKinter or how it would interact with queues, so I don't have any more suggestions :(

FoiledAgain
May 6, 2007

QuarkJets posted:

General advice in the thread has been to abandon TKinter and go with wxPython or PyQt. I'm not really familiar with TKinter or how it would interact with queues, so I don't have any more suggestions :(

The problem I don't think is necessarily related to Tkinter. Mainly my question was "how do I get the value of a variable from a process that is running". If I can just get the value of .current_generation, I'm sure I can find a way to feed it properly into Tkinter.

edit: ugh, this is embarrassing. The whole problem was that I didn't grid the frame that the progress bar was in. Wow... Thanks for reading!

FoiledAgain fucked around with this message at 22:02 on Jul 24, 2013

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

QuarkJets posted:

General advice in the thread has been to abandon TKinter and go with wxPython or PyQt. I'm not really familiar with TKinter or how it would interact with queues, so I don't have any more suggestions :(

I don't use any of them very often, but I think PySide is supposed to be better in some sort of way than PyQt...

Adbot
ADBOT LOVES YOU

Posting Principle
Dec 10, 2011

by Ralp
The main problem with PyQt is the GPL. PySide is still on 4.8 while PyQt has support for QT5. Both support Python3.

Posting Principle fucked around with this message at 22:50 on Jul 24, 2013

  • Locked thread