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.
 
  • Post
  • Reply
Dex
May 26, 2006

Quintuple x!!!

Would not escrow again.

VERY MISLEADING!

shrike82 posted:

Which is a roundabout way of saying that Boris was right with his initial solution.

well i said he was directly right with my first reply, that last one is just using __get__ instead of methodtype syntax since it's new to me and reads a bit cleaner imo, since it just does that under the hood

Adbot
ADBOT LOVES YOU

breaks
May 12, 2001

Boris Galerkin posted:

The way I thought of it was that everything is being passed around by reference/pointer. So when I assign test.foo = foo what I'm actually doing is saying "hey test object, your memory location corresponding to "foo" is now pointing to this other memory location which happens to have information on how to execute the foo function.

I'm not sure if that's right or not but from a Fortran background it made perfect sense …

It is basically correct. As some of the previous posts were getting at, the Python function type implements the descriptor protocol. When you look up an attribute located in the class's namespace on a class or an instance of a class, if the object has a __get__ method, that's called and it's return value is what you get from the attribute lookup instead of the object itself. This is explained in more detail in the docs on the descriptor protocol. But point being, when you do Class.foo = some_function and then Class.foo or Class().foo, you are getting a newly created wrapper around the function and not the function itself.

Another fuckin edit to add: Today I also learned that this is changed from Python 2->3. In Python 2 you get an unbound method for the Class.foo lookup and in Python 3 you just get the function itself. But the descriptor mechanics are the same, what __get__ is returning is different.

Though again, unless this is just an experiment for learning about Python rather than actual in-use code, I think you are better off just calling the function with the instance as a parameter rather than doing the thing that we've had a 20-post discussion about the exact mechanics of.

More funny stuff:

code:
Illustrating the point about descriptors:

>>> class C:
	pass
>>> def f(arg):
	print("f")
>>> C.func = f
>>> inst = C()
>>> inst.func_ = f
>>> inst.func is f
False
>>> inst.func_ is f
True
>>> C.__dict__['func'] is f
True
>>> C.__dict__['func'].__get__(inst, C) is f
False

But this part surprised me:

>>> C.__dict__['func'].__get__(inst, C) is inst.func
False
>>> id(C.__dict__['func'].__get__(inst, C)) == id(inst.func)
True
In general the expectation is that id() == id() and is are equivalent. I think this happens basically because 1) you are getting a new method object each time __get__ is called and 2) the CPython implementation tries to cache the method object structure and reinitialize it with new data when it needs another one instead of allocating new memory each time. So in the id case presumably the method object from the call to __get__ gets deallocated when the id function call is over, the list pointer gets backed up one spot, and then the same structure in C is reinitialized with the data from the inst.func lookup. In CPython the object's location in memory is used for the id so they end up being the same. That seems to be the general idea anyway, I didn't go through it carefully enough to make sure that's 100% right.

Sorry I edited this a few times and search/replaced "c" with "inst" in the code because it was hard to read.

breaks fucked around with this message at 08:57 on Apr 19, 2017

shrike82
Jun 11, 2005

As always, 'Fluent Python' has something to say about this with chapters on descriptors and meta-programming.

Boris, I'd recommend you get it if you haven't, if you really want to delve into the languages.

Boris Galerkin
Dec 17, 2011

I don't understand why I can't harass people online. Seriously, somebody please explain why I shouldn't be allowed to stalk others on social media!

Nippashish posted:

This is sort of weird, but what you want is also sort of weird. "I want a function that does different things depending on which instance I call it on" really screams "I want a base class with a bunch of different subclasses" to me.

You're not wrong, but I wanted to avoid having to explicitly make new subclasses and instead just have them all represented by one class called "NavierStokes" in this case. So that's why I asked about metaclass vs methodtypes.

Dex posted:

code:
import types

class Example(object):
    def __init__(self, value):
        self.value = value

    def bind_function(self, myfunc):
        return setattr(self, myfunc.__name__, types.MethodType(myfunc, self))

This is essentially what I had in my first post:

Boris Galerkin posted:

code:
self.foo = types.MethodType(module.foo, self)

The question was just: should I metaclass or use the types.MethodType module? I didn't really see or understand a practical difference.

shrike82 posted:

Which is a roundabout way of saying that Boris was right with his initial solution.

From Hettinger's Descriptor HowTo
code:
class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj, objtype)
I think everyone here, including me, just found out that attaching a function to an instance doesn't automatically bind it, which is an interesting quirk.

I'm not sure I understand what this one is doing.

Thanks for all the help and discussion. I don't want to sound dismissive, but it looks like the original method I proposed works and Dex's solution is more or less the same, so I'm just going to stick with what I have.

shrike82
Jun 11, 2005

Basically, and to your earlier question, when you use dot notation in Python (Class.attribute or Instance.attribute), you're not directly accessing the attribute.

You're calling the __setattr__ or __getattribute__ (and potentially __getattr__) magic functions and passing the attribute to those functions. Attributes that implement the Descriptor protocol (i.e. implement __get__ and/or __set__ functions) affect the earlier mentioned magic functions. Because functions implement the __get__ function, there's some funkiness.

Your thought about using MethodTypes to manually bind the function is right.

breaks
May 12, 2001

I'm sorry-not-sorry to reiterate it again but keep in mind that doing self.something = types.MethodType(some_func, self) in __init__ or whatever does not exactly replicate the behavior of a normal method and with enough usage there will eventually be a situation where the fact that you have a MethodType in the instance namespace instead of a function in the class namespace becomes a problem even though it "works like a method."

If you don't care you don't care but do enough of this stuff and it will eventually bite you in the rear end in a very painful way unless you are really taking pains to exactly replicate the normal behavior. It is genuine Bad Python to drop a MethodType on an instance like that because it is subverting the expectations of the language implementation. I'll stop harping on it because I think I've said it too many times already.

breaks fucked around with this message at 10:29 on Apr 20, 2017

shrike82
Jun 11, 2005

Again,

from Hettinger's Descriptor HowTo
code:
class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj, objtype)
Or
https://twitter.com/raymondh/status/771628923100667904

Which is effectively the same

I'm very well aware of the issues with playing with metaprogramming, but just saying it's bad without providing a feasible alternative kinda sucks.

shrike82 fucked around with this message at 10:35 on Apr 20, 2017

breaks
May 12, 2001

The descriptor howto is a great read and generally correct but has some simplifications, imprecise language, and outdated info. That code throws an exception on 3.6.1, and if you fix that the Class.Function lookup returns a bound method, etc etc; it isn't fully equivalent to how it actually works, at least not at this point.

Partial is fine. It's not pretending to be a method and then actually behaving in slightly different ways. But passing in the function and adding a method to call it with self is basically the same thing, and has already been suggested two or three times and the code written out for it at least once. The guy doesn't seem interested because it's not "injecting a method."

Space Kablooey
May 6, 2009


I still think subclassing is the better option, if anything because it is the simplest way.

shrike82
Jun 11, 2005

There's nothing odd about talking about dependency injection, outside of DI/IoC being slightly less 'popular' in Python-land due to dynamic typing making it trivial to handle.

Boris Galerkin
Dec 17, 2011

I don't understand why I can't harass people online. Seriously, somebody please explain why I shouldn't be allowed to stalk others on social media!

breaks posted:

The guy doesn't seem interested because it's not "injecting a method."

No.

I wasn't interested in passing in a literal function into the constructor of the class because I wanted the class constructor to do it for me.

I understand that I could have still written my class to "attach" the proper function to itself and then call it with explicitly passing in "self" into the function to replicate the same thing.

But my "there has to be a better way" lightbulb lit up since it seemed silly and I found metaclass and MethodType.

And also

breaks posted:

If you don't care you don't care but do enough of this stuff and it will eventually bite you in the rear end in a very painful way unless you are really taking pains to exactly replicate the normal behavior. It is genuine Bad Python to drop a MethodType on an instance like that because it is subverting the expectations of the language implementation. I'll stop harping on it because I think I've said it too many times already.

This is literally the first response from anybody with substantial information on why what I'm doing may be considered "bad." Everyone else was either helpful and suggested methods to do what I wanted to do or tell me "no don't" without offering why.

Gene Hackman Fan
Dec 27, 2002

by Jeffrey of YOSPOS
I'm wanting to build a controller program for some physical computing equipment of mine, but in trying to set up Kivy, I've run into a problem where Windows 10 only shows that it has OpenGL 1.1. Kivy is saying it needs OpenGL 2.0 in order to run.

Has anyone a) found themselves in the same position, and b) found a workaround?

Barring that, does anyone have a suggestion for packages that build a GUI with about the same learning curve as Kivy?

Dex
May 26, 2006

Quintuple x!!!

Would not escrow again.

VERY MISLEADING!
i was going to suggest looking at GLEW but it seems kivy already has it as a dependency:

https://kivy.org/docs/installation/installation-windows.html posted:

python -m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.deps.glew

have you installed all those packages already?

Gene Hackman Fan
Dec 27, 2002

by Jeffrey of YOSPOS

Dex posted:

i was going to suggest looking at GLEW but it seems kivy already has it as a dependency:


have you installed all those packages already?

I have -- next time I'm at the computer I'll screen shot the error codes. I think it has more to do with Windows insisting on using the generic PnP display driver (which is set on OpenGL 1.1)

xpander
Sep 2, 2004
We were talking about Zappa and Lambda a few pages ago, and Thermopyle had mentioned that a lack of Python 3 support was the real thing holding him back from starting new projects with it. That's now been remedied: https://aws.amazon.com/about-aws/whats-new/2017/04/aws-lambda-supports-python-3-6/.

Eela6
May 25, 2007
Shredded Hen

Boris Galerkin posted:

Thanks for all the help and discussion. I don't want to sound dismissive, but it looks like the original method I proposed works and Dex's solution is more or less the same, so I'm just going to stick with what I have.

You took a good look at alternative suggestions and then made an informed decision. That's not dismissive in the least. You brought up an interesting question in an area that's relatively niche/complex within python. If nothing else, I learned a lot from the discussion!

Just because Metaclasses and method injection are the wrong solution most of the time doesn't mean they're the wrong solution all of the time.

Gene Hackman Fan
Dec 27, 2002

by Jeffrey of YOSPOS

Gene Hackman Fan posted:

I have -- next time I'm at the computer I'll screen shot the error codes. I think it has more to do with Windows insisting on using the generic PnP display driver (which is set on OpenGL 1.1)

Yeah, here's what it gave me the last time I tried to run a basic "hello world:"



edit: I know I've heard other people having issues with this and added a line or two to the actual program to force... something, but it hasn't worked for me:
code:
from kivy import Config
Config.set('graphics', 'multisamples', '0')
Also, here's the dump from the console window:

code:
[INFO   ] [Logger      ] Record log in C:\Users\Teacher\.kivy\logs\kivy_17-04-20_6.txt
[INFO   ] [Kivy        ] v1.9.2.dev0, git-e831904, 20170420
[INFO   ] [Python      ] v3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [OSC         ] using <thread> for socket
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] No framebuffers extension is supported
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'1.1.0'>
[INFO   ] [GL          ] OpenGL vendor <b'Microsoft Corporation'>
[INFO   ] [GL          ] OpenGL renderer <b'GDI Generic'>
[INFO   ] [GL          ] OpenGL parsed version: 1, 1
[CRITICAL] [GL          ] Minimum required OpenGL version (2.0) NOT found!

OpenGL version detected: 1.1

Version: b'1.1.0'
Vendor: b'Microsoft Corporation'
Renderer: b'GDI Generic'

Try upgrading your graphics drivers and/or your graphics hardware in case of problems.

Gene Hackman Fan fucked around with this message at 20:09 on Apr 20, 2017

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4

shrike82 posted:

There's nothing odd about talking about dependency injection, outside of DI/IoC being slightly less 'popular' in Python-land due to dynamic typing making it trivial to handle.

As a relative newbie, if dependency injection is less popular in Python than it is in other languages, how do you handle cases in Python that you'd typically use dependency injection for in, say, Java?

Thermopyle
Jul 1, 2003

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

Epsilon Plus posted:

As a relative newbie, if dependency injection is less popular in Python than it is in other languages, how do you handle cases in Python that you'd typically use dependency injection for in, say, Java?

DI isn't exactly uncommon in Python. It's just that because of Python's dynamic nature you don't really need a lot of scaffolding that you need in other languages so it often doesn't go by the Official Pattern Name Dependency Injection. You just write stuff in Python in a pythonic way and then later someone is talking about Python and DI and you go "you know I guess I just did use DI!"

edit: Forgot to add that super() is an effective and easy way of doing DI in python.

Thermopyle fucked around with this message at 21:51 on Apr 20, 2017

Dex
May 26, 2006

Quintuple x!!!

Would not escrow again.

VERY MISLEADING!

Gene Hackman Fan posted:

edit: I know I've heard other people having issues with this and added a line or two to the actual program to force... something, but it hasn't worked for me:
code:
from kivy import Config
Config.set('graphics', 'multisamples', '0')

seems to be a pretty common problem with windows 10 users:
https://github.com/kivy/kivy/issues/3576 - this one is fixed by the multisampling config you posted, so it's not that
https://github.com/kivy/kivy/issues/5071 - this one is pyinstaller specific
https://buffered.com/support/solve-opengl-error/ - this is just some random app that uses kivy

if you have the latest graphics drivers installed already, i'd say open an issue on kivy's github and see if they have anything helpful to add

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4

Thermopyle posted:

DI isn't exactly uncommon in Python. It's just that because of Python's dynamic nature you don't really need a lot of scaffolding that you need in other languages so it often doesn't go by the Official Pattern Name Dependency Injection. You just write stuff in Python in a pythonic way and then later someone is talking about Python and DI and you go "you know I guess I just did use DI!"

edit: Forgot to add that super() is an effective and easy way of doing DI in python.

I've tried to figure out super() in Python a few times and everything I look at makes no goddamn sense; do you ? have any good resources covering it? I don't mind doing regular old DI for the project I'm doing in Python it would be nice to properly understand how super() works.

shrike82
Jun 11, 2005

Epsilon Plus posted:

As a relative newbie, if dependency injection is less popular in Python than it is in other languages, how do you handle cases in Python that you'd typically use dependency injection for in, say, Java?

Sorry, I meant that it's so trivial in Python that people don't tend to think "Oh, I need to use a DI/IoC framework here".
More generally, and imho, people spend less time thinking about design patterns when building stuff in Python.

This is a good read if you want to learn more about Python design patterns
http://www.aleax.it/gdd_pydp.pdf

shrike82 fucked around with this message at 01:28 on Apr 21, 2017

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

shrike82 posted:

Sorry, I meant that it's so trivial in Python that people don't tend to think "Oh, I need to use a DI/IoC framework here".
More generally, and imho, people spend less time thinking about design patterns when building stuff in Python.

This is a good read if you want to learn more about Python design patterns
http://www.aleax.it/gdd_pydp.pdf

The main use I see of IOC containers is magically getting constructor args on creation by registering classes and interfaces which is v unpythonic

Otherwise just pass them in as arguments

Eela6
May 25, 2007
Shredded Hen

Epsilon Plus posted:

I've tried to figure out super() in Python a few times and everything I look at makes no goddamn sense; do you ? have any good resources covering it? I don't mind doing regular old DI for the project I'm doing in Python it would be nice to properly understand how super() works.

Super() considered super by Raymond Hettinger is a good resource.

Raymond did this as talk at PyCon a couple years back so it's available as a video presentation too. Raymond is a fantastic presenter.

As always, Fluent Python covers this in some detail.

shrike82
Jun 11, 2005

I've forgotten most of my Java but doesn't it have the super keyword which is used roughly in the same way?

Azuth0667
Sep 20, 2011

By the word of Zoroaster, no business decision is poor when it involves Ahura Mazda.
I'm not sure what this would be called but, is there anything for python gui making that is similar to what VB.net has where you can place all the widgets on a template?

I've been slamming my face into tkinter with little to no progress for long enough that I'm ready to try something new.

Dominoes
Sep 20, 2007

Azuth0667 posted:

I'm not sure what this would be called but, is there anything for python gui making that is similar to what VB.net has where you can place all the widgets on a template?

I've been slamming my face into tkinter with little to no progress for long enough that I'm ready to try something new.
Qt Creator (Designer?). It's a WSIWYG editor, but learning how to use Qt is difficult.

Azuth0667
Sep 20, 2011

By the word of Zoroaster, no business decision is poor when it involves Ahura Mazda.
I've seen PyQT recommended before for making GUIs. How does it compare to tkinter?

FoiledAgain
May 6, 2007

Azuth0667 posted:

I've seen PyQT recommended before for making GUIs. How does it compare to tkinter?

I've built GUIs with both. PyQt is considerably more powerful and I prefer using it. You get much nicer looking widgets too. At the same time, PyQt is more complex, and I found it harder to learn (harder even than Tkinter which was my first ever attempt at GUI programming). The model-view system and the signal-slot system are the usual stumbling blocks for learners. One downside is that there's practically no official documentation of PyQt. What exists is mainly for the C++ version of Qt. However, there is some good documentation for PySide, which is extremely similar to PyQt. Although I use PyQt, I find myself reading the PySide docs more often.

Azuth0667
Sep 20, 2011

By the word of Zoroaster, no business decision is poor when it involves Ahura Mazda.
Well crap the big stumbling block I'm still having with tkinter is that none of the example code I can find is current so all these tutorials I attempt get hung up at some point because something has changed.

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.
I don't know what your specific application is but nine times out of ten when someone is asking for a GUI toolkit the right answer for their use case is HTTP.

vikingstrike
Sep 23, 2007

whats happening, captain
Thanks for the Fluent Python suggestion, thread. Started reading it last week and it's been really good.

grenada
Apr 20, 2013
Relax.
Newbie question: I'm trying to build a web scraper with Beautiful Soup that pulls table rows off of the roster pages for a variety of college sports teams. I've got it working with regular HTML pages, but it doesn't seem to work with what appear to be Angular pages. Some quick googling makes it seem like I will need to use a python library like selenium to virtually load the page in order to scrape the html tables on the page. Would a work around be to first use Beautiful Soup, but if a table row returns as None, then call a function to try scraping the page using something like selenium. Or, should I just try to scrape all of the pages with selenium or a similar library?

Thermopyle
Jul 1, 2003

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

KernelSlanders posted:

I don't know what your specific application is but nine times out of ten when someone is asking for a GUI toolkit the right answer for their use case is HTTP.

I assume you mean HTML. And I agree with you.

Vivian Darkbloom
Jul 14, 2004


I have an interview next week where I'll have to demonstrate working knowledge of Python. I do have a basic understanding of the language and what to do with it, but I wondered if there were any good online resources for intermediate Python practice. Unfortunately I don't have a lot of clarity about what I'll be tested on and I'm not working on any special project at the moment, so I'm not sure how to practice.

Eela6
May 25, 2007
Shredded Hen
The best thing you can do to get basic fluency is to take a project you've written before in another language and re-inplement it in Python.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

laxbro posted:

Newbie question: I'm trying to build a web scraper with Beautiful Soup that pulls table rows off of the roster pages for a variety of college sports teams. I've got it working with regular HTML pages, but it doesn't seem to work with what appear to be Angular pages. Some quick googling makes it seem like I will need to use a python library like selenium to virtually load the page in order to scrape the html tables on the page. Would a work around be to first use Beautiful Soup, but if a table row returns as None, then call a function to try scraping the page using something like selenium. Or, should I just try to scrape all of the pages with selenium or a similar library?

In my experience Selenium isn't exactly fast, but really it depends on how many pages you need to scrape and how often, and also how heavy they are (like does it take a full 20 seconds for all the jabbascripts to render). In the worst case you'll have a browser window literally opening and loading the page, and you'll have code waiting and checking if it's ready yet

Honestly it depends on the pages you're loading, unless they all happen to share the same structure (these are separate sites right) you'll have to hand craft some code to pull out the relevant table on each page. Ideally that's as simple as writing a selector tailored to that page's html, but if you're doing that anyway, you might as well explicitly set the type of scraping while you're at it

I don't remember the syntax but you could make a class that takes a selector and handles normal parsing (normal GET, pulls out selector using Beautiful Soup). Then you could do a similar one that does the same, but loads the page with selenium, keeps trying to find the element described by the selector (might not be in the DOM yet), and eventually times out

That way you have two basic kinds of behaviour, and you can list all your sites as Normal(url, '#cool-table') or Webdev(url2, '.stuff > table') and iterate over them calling the parse method on each. This might not be the best design but it's pretty simple if it works for you?!

Also I forget but you might be able to just get away with using Selenium and running its selector functions (which are a lot like Beautiful Soup's) on plain http responses, so no need for BS in that case. Also Selenium was a real pain last time I used it, they updated something so the Firefox webdriver wasn't included anymore and everything broke. There might be a better scraper out there?

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.

Thermopyle posted:

I assume you mean HTML. And I agree with you.

I meant HTTP, HTML, CSS, and maybe a tiny bit of Javascript, but just picked one. Thought about saying "Flask" but thought that would be too indirect to be helpful.



Vivian Darkbloom posted:

I have an interview next week where I'll have to demonstrate working knowledge of Python. I do have a basic understanding of the language and what to do with it, but I wondered if there were any good online resources for intermediate Python practice. Unfortunately I don't have a lot of clarity about what I'll be tested on and I'm not working on any special project at the moment, so I'm not sure how to practice.

Do some of the coding problems from https://www.careercup.com/page?pid=coding-interview-questions. Actually implement them, don't just think through it. Practice both on a whiteboard and in a text editor/python cli.

shrike82
Jun 11, 2005

Actually, go to platforms like hackerrank and codewars. They have algo problems as well as Python specific problems with a built-in interpreter that runs your program and compares its output for a bunch of test cases.

Adbot
ADBOT LOVES YOU

Vivian Darkbloom
Jul 14, 2004


Those are some useful suggestions, thanks. I've been using hackerrank and it seems to be helping a bit.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply