|
There's another pattern I've seen (forget the name) where you have a list of handlers and you just fire your arguments at them until one of them goes 'yeah I've got this'. That way all the type checking goes on in the handler classes and only for the types they handle, and adding more cases just means writing a handler and adding it to your list Feels a bit Java but I saw it on Python examples sooo
|
# ¿ Aug 6, 2017 19:14 |
|
|
# ¿ May 16, 2024 11:06 |
|
Yeah a lot of it's about knowing what BeautifulSoup can do and if it can make massaging your data easier, like maybe you can use getText(), that kind of thing I'd say your 'take 10' bit should come at the end though. Get a pipeline going converting your data, and only pluck off what you need when you're going to do your average or whatever. Use generator comprehensions if you don't want to process more than you need
|
# ¿ Aug 26, 2017 21:24 |
|
hooah posted:The problem with doing that is there are elements that have the specified class which aren't numbers, so I can't convert all the elements first. I didn't know about generator comprehensions, though; I'll look into those. You might want to do something like this Python code:
The other aspect is I used a few BeautifulSoup conventions to cut the code down - stuff like using property and method notation instead of typing 'find' and 'find_all' which cuts down on things and makes one-liners look nicer. I split out the actual 'convert cell contents into a number' bit into its own function, and the actual conversion step looks a bit nicer for it I think I threw in a generator expression for the hell of it (no need to create temporary lists everywhere) but it doesn't really matter here, and I did a list in the end anyway because the slice notation reads nice and python doesn't have a nice clean take(10) function yet, so whatever. Generator functions are nice for a functional pipeline, you basically set up how sequences are handled and you can do filtering and stuff at each step, so for big data you can avoid putting everything in memory. Doesn't really matter here but it's good to know about!
|
# ¿ Aug 27, 2017 00:12 |
|
You haven't closed your regex compile call on the previous line (missing the closing parenthesis)
|
# ¿ Sep 30, 2017 19:08 |
|
Line 25 just looked pretty ok to me so I figured the problem was caused before that! Also your linter should really catch that kind of thing and put a red squiggle somewhere since it's never actually closed baka kaba fucked around with this message at 19:36 on Sep 30, 2017 |
# ¿ Sep 30, 2017 19:33 |
|
At a guess something screwy was going on in your Chunk class, so when you constructed a new one you were actually reusing an array (maybe handing the same one out multiple times so they all saw every append), or doing something with your pix list or the original Image object, something like that Honestly in these situations the best thing is to run it through a debugger, set it to pause in a useful place so you can poke around at the current state of things, and you'll probably get an idea of where things are going wrong. Sometimes it's an obvious bug, other times it gives you a direction to investigate
|
# ¿ Nov 29, 2017 22:17 |
|
Cingulate posted:"while" solutions usually feel rather un-pythonic to me. I think if you want to iterate over an iterable, you should iterate over the iterable! Well guy hasn't been programming for a while! So long as it works that's the main thing, you can clean it up later oh wait now I remember, it does not have that and you have to write your own which is bad. Thanks python! baka kaba fucked around with this message at 22:25 on Nov 29, 2017 |
# ¿ Nov 29, 2017 22:20 |
|
Noice! It would be cool if you could supply a pattern that says which chunks get glitched (so you can have some clean parts and maybe make the shapes everyone loves) or make the randomisation function get more pronounced as it goes, so it gets more glitchy as you go down the image
|
# ¿ Nov 30, 2017 01:49 |
|
Hughmoris posted:How is python+selenium for filling out lots of repetitive forms? I noticed that some people on my project team are manually entering in the data for 2000+ users in to a web portal. They've asked for help but my eyes will fall out of my head if I have to manually type in crap. It is basically automating someone sitting at the computer and doing all that stuff though, probably take a while. Is it possible to use something like Requests and just POST the form data that's being sent, without having to load their web pages?
|
# ¿ Dec 5, 2017 03:53 |
|
Hughmoris posted:Automation engineer sounds pretty cool. Honestly it's easy if it's possible - a lot easier than writing Selenium code (and all the edge case stuff to make sure the page is fully loaded, etc) Here's how you set up a Session so all your requests can use the same login deets automatically Here's how you POST some keys and values (spoiler: you just hand it a dictionary) Here's how you can check the response status and make sure it worked You can either look at the webpage to see what url the form is POSTing to, and all the key names for each of the inputs, or like someone said you can use Chrome's DevTools to spy on what the browser's POST request actually contains (just fill out your form, open the Network tab and empty it if necessary, then send your form and check out the request that pops up) The main issue I can see is that your form might be sending a user ID or some other identifying token, and maybe the only way you can get that is to search for their name? You might be able to do that with requests too... but yeah, if you can just do your own HTTP it'll be way faster and simpler. But if you also want to learn Selenium, this is a good way to do it!
|
# ¿ Dec 5, 2017 08:56 |
|
These are important if you don't know 'em: https://www.youtube.com/watch?v=XOkNJxvNtPw Code completion (ctrl+space), using snippets and templates, and quick fixes (alt+enter) instead of typing all the dang code, and stuff like auto formatting https://www.youtube.com/watch?v=jmTo5xTRka8 These are huge: turn off your tabs, hide the tab bar because you don't need it, preferably put away your mouse for a bit, gotta go fast
In the help menu there should be a 1-page pdf of keyboard shortcuts - have a look at that, because it lists a bunch of cool features that make you go 'wait... is that...?' and then you find out it is. I forget if pycharm has it, but there should also be Productivity thing in help too, that shows you features you use a lot and how much typing they've saved you, but also lists stuff you might not know about. And there's the tips popup too of course I don't know exactly how much crossover there is with IntelliJ, but this is a good talk that's old but entertaining and most of it should carry over. Get you feeling extremely powerful. Covers cool things including double-tap ctrl to add extra carets with the arrow keys (what, you work on one line at a time? ) and uhhh alt+backspace or something to jump to the last edit position, all kinds of stuff https://www.youtube.com/watch?v=h8wRC7Qkcb8
|
# ¿ Dec 11, 2017 18:42 |
|
Now that's irony
|
# ¿ Dec 20, 2017 20:19 |
|
You can also doPython code:
which gives you all the name/extension combos for each server. It's an iterable representing each server, each item is an iterable of all that server's combos, held in tuples. So you can use chain to unpack all those nested iterables and just spit out one sequence of tuples, and join 'em up however you like (also it reads nicer if you change "d1" to "names" and "d2" to "extensions" or whatever!) baka kaba fucked around with this message at 00:09 on Dec 22, 2017 |
# ¿ Dec 22, 2017 00:05 |
|
Oh I meant in mine really, just that attribute[server] will read more clearly, so it's obvious what you're getting the product of
|
# ¿ Dec 22, 2017 12:31 |
|
VikingofRock posted:Why does this happen? (Python 3.6.3) http://quickinsights.io/python/python-closures-and-late-binding/ Yr lambdas are getting defined, with val as a reference to the local variable in your loop (not inlined as a constant), and when you run the lambdas they all look up the value of val. The loop has already finished running when you call them, so in each case val is set to the last value it was assigned during the loop, i.e. 3.0. baka kaba fucked around with this message at 00:14 on Dec 27, 2017 |
# ¿ Dec 27, 2017 00:10 |
|
Assuming you're importing Ex45 into Engine.py too (since you're calling Intro() and that class is defined in the other file), you've got a circular dependency - both modules depend on each other There's an explanation here with examples - the problem is you start to load file A, and it gets to the import statement and has to load file B. File B wants to import A - and that's fine, it's happened already, but it hasn't finished loading A yet. So you get to the line where it tries to use something from file A, Python hasn't seen that function or class yet (it doesn't exist as far as it's concerned), so it throws an error At this point you're probably thinking ugh this is bad and complicated and why did I bother - and yeah, often it's better to keep things in the same file. Or you have to organise the project so you don't get circular dependencies. If it's unavoidable, a lot of people recommend putting your imports at the end of the file (so they only run after the file has been fully loaded)
|
# ¿ Jan 15, 2018 12:32 |
|
A loop... loops! It can go around multiple times, until some condition is met The if/elif stuff is just a conditional - you go through it once, and follow the first branch that matches, then you pop out the other side You can put a conditional inside a loop of course, which is pretty common - iterating over several things, doing something different based on the current situation each time around baka kaba fucked around with this message at 02:08 on Jan 23, 2018 |
# ¿ Jan 23, 2018 02:06 |
|
If it helps, variables in python are basically just keys in a dictionary, so you can just go thing = whatever at any time and it just stores that key/value pair. So there's no need to pre-declare that variable like you would in other languages where you want to reuse the same reference - you're just overwriting the same entry in the dictionary
|
# ¿ Jan 24, 2018 11:38 |
|
The easiest thing would be to add the numbers as you do the counting - I'm guessing you're splitting the sentence on whitespace, and doing something smart about punctuation, so that would be a good time to decide where the count should go (like it needs to go before that colon in the first sentence, but apostrophes would be treated differently etc). So you'd take each word, count it, then transform the string to add the count, and eventually just use join to put it all back together If you're in the situation where the counts have already been done, you just need to get back to that state again - split each sentence into words. Then you'll have two structures that mirror each other (a list of lists of words, and a list of lists of counts), and you can iterate over those together, using zip to get pairs of word lists and count lists, and using zip again on those to get pairs of words and counts tldr you're probably looking for zip
|
# ¿ Jan 26, 2018 15:00 |
|
If you look at the error, it's saying you can't do str() <= int(), and there's something that looks like that in the line it quoted you're casting to int after you've done the comparison - you need to get used to the order it's written in python, but it does the for bit to get items, then the if bit to filter them, and then it does the bit on the left with the results. You can think of the for part as item from items (where item passes this test)
|
# ¿ Jan 28, 2018 21:44 |
|
Yeah ideally you'd convert all that as you parse it. Read in each line, split it and convert each item to an int. That way your "get input" part hands you a pristine set of int lists, which is the structure you want to work with
|
# ¿ Jan 29, 2018 00:10 |
|
wasey posted:
You need to work out your plan first. Basically (if I'm reading this right) what you want to do is:
and the activity parsing bit goes
hopefully that makes it a bit clearer it's the "do something with that data" where you need to store your activities You might not want to use classes, but only because it's not 'pythonic' - there's nothing wrong with using them while you get your head around the problem. It's just there are simpler tools you can use that will do the same job here (better, even) edit- it might help to explain exactly what you want to have at the end of this. How should it be organised? Do you need to store the 11 and 3, what do they represent? baka kaba fucked around with this message at 19:24 on Feb 3, 2018 |
# ¿ Feb 3, 2018 19:22 |
|
I think you'll have to post your code to know if there's a more elegant way, but I don't think Python really encourages anything besides the ol' for loops in this case Some languages have some kind of window function, which you could use to produce a sequence of each element and its successor (so in your case (0, 14), (14, 18), (18, 20) etc). That way you get a stream of items and the thing you need to compare them to, and you can start to group them based on whether they meet your rule or not. Python doesn't have this though, for some reason It does have a reduce function but again, I'm not sure I'd exactly call it elegant here - it's definitely not as Pythonic (i.e. readable to general Python users) as a bunch of loops and conditionals doing the same thing Python code:
|
# ¿ Feb 8, 2018 21:29 |
|
The more pythony way might be to have a generator that yields lists (basically consumes the iterator, adding each item to a list it's building until the item is too big, yields the old list and creates a new one for the item). That way you can feed that into another generator that filters out the single lists, or have the first generator just not yield a single item list
|
# ¿ Feb 9, 2018 00:28 |
|
I was thinking more likePython code:
You can do a length check before you yield (so you only get lists with 2 or more items), but there's two problems - one is that you have to put that code in there twice (you're yielding in two different places), and it also ties that implementation detail into the grouping function. It doesn't just split your list into groups where each item is close to the last, it also does another job of removing lists below a certain size. Personally I'd argue those are two different things (you might not even want the filtering all the time, or you might want to change the size limit), so it makes sense to do that separately, running it on the results of the grouping function The nice thing about generators it's they're on-demand, so you can put them together like a pipeline. Instead of producing a full list of groups, and then producing another list where some of those groups are missing, that code up there iterates over big_groups, asking it to produce a single group each time. (big_groups is a generator comprehension, like a list comprehension but in ( ) so it produces a generator.) So in turn, big_groups asks grouped for an item, which it yields when it's built one. If big_groups discards it (because it doesn't meet the 'big enough' condition) then it asks for another one, until it has something it wants to yield That doesn't necessarily matter, but you can see how you can set up a big chain that yielded items have to pass through, getting tweaked or dropped or whatever, creating a machine that produces single, finished items on demand. And that can be good for working with very large amounts of data, or something slow where you want to drop things as early as possible if you're not going to be using them later in the pipeline baka kaba fucked around with this message at 02:36 on Feb 9, 2018 |
# ¿ Feb 9, 2018 02:28 |
|
Wallet posted:I take your point about them being different functions, though in this case there isn't really a context where you'd want length 1 groups. Sure, that works! I feel like you're introducing a lot of complexity just to have a single yield statement in there though, and it's less clear what job it's actually doing. Personal preference obviously And the thing with putting the filtering outside... I guess it's more of a functional approach, where you're encouraged to write smaller, simpler single-task functions and then compose them together - not necessarily because you're gonna use them in isolation too, just that it's really readable when you look at each one or the code that chains them together It's great for writing pipeliney stuff, especially if you name your functions well, because you can see exactly what it's doing as a set of steps - like I had to infer you were dropping those groups by the example result you posted, but adding a line that filters them out makes it explicit, and you don't need to rely on comments either. Personal preference again of course!
|
# ¿ Feb 9, 2018 05:14 |
|
If that's not clear, instead of replacing each string in the list with a new "great" version, you're just creating a new list by taking elements from the original, doing something with them and sticking the results in your new list. LikePython code:
Also this is a little advanced, but you can print all your magicians in one line: Python code:
Not saying this is better in this case, but it's good to know!
|
# ¿ Feb 9, 2018 17:58 |
|
Another way you can look at it is, usually you do for thing in stuff to get a sequence of items, easy. If for whatever reason you want to number those items too, just call enumerate and it'll handle the counter and pass you the number with each item. The work's already done for you, there's less chance of making a mistake, it's clear what's happening, and if you don't unpack it as count, item then you have a tuple ready to pass into something else, you don't need to build it yourself
|
# ¿ Feb 9, 2018 18:33 |
|
Slimchandi posted:When I was learning Python basics, it took me a long time to realise that when using a list comprehension, you can use any name in the for part. As well as what people have said, print takes varargs anyway, so you can unpack an iterable like my example a couple of posts ago Python code:
it might make more sense to use a generator comprehension instead though, since you don't really need the list Python code:
|
# ¿ Feb 10, 2018 02:21 |
|
Cingulate posted:In this case, Doh yes
|
# ¿ Feb 10, 2018 20:23 |
|
I guess there isn't really a use for it since you can do *name, especially with the Python philosophy of having one way to do a thing. It would be more convenient if the separator was supplied from elsewhere, so you always get consistent behaviour, but heySlimchandi posted:For clarity, I was referring to functions with side effects or return None rather than just callables. The given example was exactly what I intended. It's convenient in the sense that a 2-line (or 3 with a conditional) for loop can be put on 1 line instead, or even more complicated nesting. It gets to a point where that might be less clear about what you're doing though The problem is that list comprehensions generate a list, that's their whole purpose. When someone reads your code, and they see a list comprehension, they see you generating data, they don't see the side effects. You can argue that the clues are all there because a) you're not keeping the list and b) it's calling print() and everyone knows what that does, but that's not always necessarily true. The actual purpose of your code is implicit instead of explicit. (You're also actually generating a list full of Nones, which is grody garbage at best and might actually cause memory issues at worst) Unfortunately Python doesn't seem to have any equivalent to forEach, where you'd have something like for_each(function, iterable) and it would explicitly call the function with each element, returning nothing. There's a consume recipe in itertools but that means it's not actually in the standard library, for reasons, and you'd have to put it in your own code somewhere. And that means you need to add your own iterable of function calls, like consume(print(c) for c in name) or consume(map(print, name)). Which is better, in that it's more explicit, but I think the plain for loop is more pythonic If you do it a lot though, no reason you can't write your own utility function to make it super explicit and concise!
|
# ¿ Feb 10, 2018 21:05 |
|
^^^ that's what I'm saying, in most cases that's probably the best way to do it Yeah I used map in my last example - it returns an iterable though, you still have to consume it by iterating over it somehow Personally I don't really like the semantics of that anyway - map is for transforming elements from one set of data into another set of data, so it produces some values. In this case you're still ignoring the results and relying on the side effects of the mapping function - like here's one way to consume that example I gave: Python code:
|
# ¿ Feb 10, 2018 21:36 |
|
That's some sweet reduce action
|
# ¿ Feb 13, 2018 21:06 |
|
map is for transforming a bunch of things (it maps values to other values, basically). So if you have a set of elements, but you want to change the NAs to 0s, your mapping function wants to output a 0 if it gets one of those, and just pass everything else through as-is (or map the value to itself, if you like)Python code:
that way the sequence of elements you get out is the same as what you put in - you've just replaced some of them with different values. What your code does is filter out all the non-NA lines (right?), leaving you with only a bunch of NAs, and then you turn those into a bunch of 0s instead - which isn't very useful! You want to keep all the elements, but use map to selectively change some as they pass through Using a regex find and replace might be a lot better anyway, I just wanted to point out what the functional stuff is about baka kaba fucked around with this message at 02:43 on Feb 26, 2018 |
# ¿ Feb 26, 2018 02:40 |
|
Probably worth benchmarking it (Python's lists are apparently arrays, so a reversed iterator should be fast?) but you could always just iterate over the array normally, assign the index to a variable whenever you find a match, and then at the end it'll be set to the index of the last matching element (or None) Array traversal should be fast either way, not sure about Python's implementation - reverse iteration is neater though (since it stops as early as possible)
|
# ¿ Mar 2, 2018 03:04 |
|
The loop protects you from the universe's ironic sense of humour
|
# ¿ Mar 5, 2018 18:25 |
|
Sad Panda posted:Next part of my Blackjack program. A lookup table. A short extract of the data would be... You could make each row a namedtuple type with a parameter for each column name
|
# ¿ Mar 5, 2018 23:31 |
|
Sad Panda posted:
Not that it really matters, but the way you're checking if no swaps happened can cause an extra pass to occur. In a list of n items you're doing n-1 comparisons each pass, but you're looking for a chain of n or more comparisons that didn't cause a swap. So with a list like 5,1,2,3,4 the 5 will bubble up on the first pass, and now the list is sorted. But you want 5 swapless comparisons, and so far you have 0, so you do another pass, and now you have a run of 4. Gotta do it another time! Now you have 8 You could change the comparison operator, but really you can do this all a lot simpler - on each pass, set a 'swapped' flag to false. If you do a swap, set it to true. At the end of the pass, if swapped is still false, you're done! You can also do smarter stuff with the looping, based on the idea that the largest item always bubbles to the right so the list gradually gets sorted from right to left (so you don't need to check those end items anymore) but bubble sort isn't very efficient anyway - that's probably why it seems slow, it is! While we're on this, this is the best one of those visualisation videos I've seen https://www.youtube.com/watch?v=sYd_-pAfbBw The hue is where the dot should be in the array, and the closeness to the centre is how out of position it is. As each one gets sorted it flies out to its position on the circle edge. Some wild stuff happens in there baka kaba fucked around with this message at 17:45 on Mar 18, 2018 |
# ¿ Mar 18, 2018 17:38 |
|
Assuming PyCharm has the same basic debugging capabilities as IntelliJ, you can add breakpoints wherever, then right-click them and uncheck pause execution (or whatever), and add your own print statement in the "execute this" bit - you can include variables and all that. It's like adding print statements without sticking them in the code But stepping through and watching what happens is your best bet
|
# ¿ Mar 19, 2018 04:19 |
|
|
# ¿ May 16, 2024 11:06 |
|
My fav thing is being able to reach in and change the value of variables (even by executing some arbitrary code) and then set it running again
|
# ¿ Mar 19, 2018 06:44 |