|
Seventh Arrow posted:Oh! I think I see. So when you're using a capital "L" list, you should iterate with integers. But with strings, not so (even if you can slice them with, say, [4: ]). Am I correct? My apologies, I misspoke by calling the string "a list", QuarkJets used the correct terminology by calling them "an iterable". The relationship both string and list have with indexes is that you can access elements in them with an integer or a slice (which is a shorthand for a specific range of integers). The thing I was hoping to have you notice (others have done a better job), is that it doesn't really make sense linguistically to pull the "Dth" or "Drd" element out of a list of numbered somethings. There are other types of data structures where this might make sense, but not the list or the string.
|
# ¿ Jun 25, 2022 02:32 |
|
|
# ¿ May 15, 2024 19:06 |
|
awk handles this by collapsing "one or more" of the separator character, which seems like it would work here you would probably be best served just ignoring the "pretty printed" header and just looking at the column labels themselves. you can generate the headers later from the parsed table data, if you need them 12 rats tied together fucked around with this message at 20:25 on Jun 27, 2022 |
# ¿ Jun 27, 2022 20:22 |
|
if you want to end up with the list/dict/set anyway, always use a comprehension. if you're using the comprehension as a terse way to obtain a specific iteration, and the iteration requires a gnarly looking comprehension, that's when you should consider unrolling. imo.
|
# ¿ Jun 28, 2022 18:10 |
|
Seventh Arrow posted:I've been learning about scopes and namespaces (and maybe not paying enough attention!), so I'm trying to understand how this works: the 3rd statement passes the function called "add_tip" to the other function. the other function receives it and executes it, binding the result to a variable called "total" this called "first class functions" or "higher order functions" or maybe some other things e: adding quote for new page, and i have attempted to shittily mspaint this for you: the key insight here is that a function is just an object like anything else in python, which means you can pass it around to other functions so it can be called later 12 rats tied together fucked around with this message at 05:20 on Aug 12, 2022 |
# ¿ Aug 12, 2022 05:05 |
|
If you find that you end up sprinklingPython code:
|
# ¿ Aug 31, 2022 19:58 |
|
Falcon2001 posted:This is obviously pretty abstracted, but is a high level summary of it. Double edit: this doesn't even contain what I asked about before. I might be an idiot. Anyway, feel free to critique this too! At some point you need to ingest and handle the ugliness of reality, that part doesn't have to be particularly clean or clever or elegant as long as it works and its understandable. You're best equipped out of all of us here to write that part. The important thing is that you fully handle it and provide a clean contract with the rest of your codebase, and it sounds like you have a good handle on that. I would add that, in general ,I try not to rely on like "whatever I return will respond to __get_item__", I generally prefer creating a class that relates to a business logic concept and has methods with named parameters and docstrings that try to map english explanations of the business logic concepts to the programming language mechanisms for interacting with those constructs. I don't think that's considered very pythonic, but python is at least partially an OO language so I feel like it's fine to rely on OO design principles when it makes sense.
|
# ¿ Aug 31, 2022 21:02 |
|
A lot of the stuff QuarkJets mentioned is less Python and more "OOP in general", I think, so you're not likely to find a python resource that does a very good job of it. The best thing I'm aware of is honestly just, posting about it online, and reading about it online (especially what makes "good code" and how its different from bad code). I think a good first step would be trying to refactor your loop into discrete problems that need to be solved and then writing a function that solves exactly one of those problems, a good example here is probably this one: Python code:
You could change this to "if already_in_table(state_string)", but I think you were right not to, because it doesn't increase the at-a-glance readability of the code just to have the sqlite query live somewhere else. That's a sign that this code is doing too much, and that the level of abstraction here is too low --> not enough information is being hidden/is encapsulated by a logical construct with a name and a signature. The more this happens, as you keep layering on new code paths and conditions, the harder it becomes over time to unwind the code and give it a name. We're basically at a point where, in order to suggest a potential refactor, we have to understand the entire codebase and the full context of the problem you're solving. Being good at OOP design is one way to combat this problem. I gave it a read-through and honestly I can say that I just can't understand it enough to offer any specific advice, except that -- Python code:
|
# ¿ Sep 30, 2022 19:52 |
|
A piece of the standard library that I personally reach for all the time when I have "collections of stuff to do" is the collections.deque, which you might find to be more ergonomic for your problem. Specifically, that you can create them, put things in them, and then get things out of them later. If you want to just handle things one at a time, the workflow is to your_deque.append() your stuff -> you can your_deque.pop() to get the "most recently appended" or you can your_deque.popleft() to get the "first appended". I suspect that you can clean up a lot of your "list with index counter that gets incremented" and "dictionary that you check the length of and del items from" with a deque, since it can be looped on, and it mutates itself as you use it: Python code:
12 rats tied together fucked around with this message at 20:11 on Sep 30, 2022 |
# ¿ Sep 30, 2022 20:06 |
|
FredMSloniker posted:Breaking every section out into its own function won't make get_state_complex look any nicer, and I'd have to define a function name for each possible section. I will be using functions for things sections have in common - for instance, 'offer three choices that only differ in what section we turn to next' or 'damage the character and turn to one section if they survive and another if they don't' - but, especially in "Impudent Peasant!", there's a lot of stuff that's unique to a single section that happens. There's two main patterns I reach for when doing this, one of them you already touched on: put the functions in a dictionary. Just for completeness, that would look something like this: Python code:
Second pattern is basically the same except instead of manually pairing a string key to a function value, you can use structural pattern matching. This is useful because it gives you a clean, ergonomic way to interpret an input object (like your game state) and dispatch to an arbitrary code path while also performing setup for that code path. The example in the link is actually input handling for a text adventure game, you might find it somewhat relevant.
|
# ¿ Oct 1, 2022 06:38 |
|
Truthy and Falsey values in python are well understood at this stage of the programming languages life, I think. Checking if something is not None is a code smell though. Python is an OOP language so avoid if statements, avoid type checks, especially avoid writing if statements that are actually type checks. Isolate the thing that is conditionally None and provide a safe API for it, don't let it propagate throughout your codebase. The place where truthy and falsey provide the most value is while loops, because the important behavior lives in one place and the truthy or falseyness of it is trivial to verify in the language's excellent suite of repl and ide tooling.
|
# ¿ Oct 9, 2022 20:38 |
|
Basically you want to get rid of the NoneTypes asap because they're, kind of by definition, the least useful type in the language. The simplest example I can think of is that "for x in response" where response is an empty list is valid code, but if response is None that's a runtime error. What are you going to do with the optional string? Is there an appropriate default value for when the string isn't present? You can encode the answers to these questions permanently in your object model, which usually tends to simplify the code, improve readability and maintainability, and other good things.
|
# ¿ Oct 10, 2022 20:12 |
|
Python handles the John Null situation in two ways: 1) None isn't actually "null", it is "the singleton instance of NoneType" which is an in-language placeholder for "the concept of nothing", but it actually is something, and that something has a (restrictive) API. This is different from other languages where Null might actually be nothing, it might be a macro that is a placeholder for "the integer 0", etc. 2) Python's NoneType casts to string as "None", so a John None would not run into any of these problems presuming that the handler for their name was running Python. They would correctly be stored as first_name John, last_name None, display_name John None. As for default arguments, because the design depends so much on the business domain, there aren't a lot of good generic resources that I'm aware of. A non trivial but still toy example I like to pull out is, pretend we're writing doordash, and we have PickupOrder vs DeliveryOrder, and we're confused about what ValidateAddress() is doing. Which address is validated, or is it both? and what happens if we don't have a delivery address? You solve this problem with OOP by extracting the things that vary, giving them names, and injecting them later at runtime. For this example, we might eventually conclude that DeliveryOrder and PickupOrder are fake, that we fooled ourselves into this failing pattern with names and inheritance, and that what we actually have here is an instance of the class FoodOrder that always has an instance of an object of the type FulfillmentBehavior, which always has ValidateAddress() (or some other wrapper method - a safe and stable API for the Order objects to consume). In our FulfillmentBehavior object model we can design-away the NoneTypes and the optionals: PickupFulfillment never has a DeliveryDriver or a DeliveryAddress, but DeliveryFulfillment always does. Both objects can be talked-to by the parent FoodOrder in the same way, both objects always "do the right thing", nowhere in the code are we checking what the anything's type is, or double checking that things aren't None. If something were None unexpectedly, we'd raise an error in the constructor, and we'd never have completed a FoodOrder object to the point where it could possibly fail to actuate its ValidateAddress method. Helpfully, at the failure call site we also have all of the information we need to reconstruct it, so we can reproduce this easily later while debugging. eXXon posted:Huh? What is smelly about either of: dict.get also makes me nervous, always. I'd rather see "if key in some_dict".
|
# ¿ Oct 10, 2022 21:26 |
|
I mean, you didn't say anything wrong (that I remember anyway, I'm phone posting). Handling nulls is hard in every language, and the tools that the language gives you to deal with them are important. As a strong/dynamic language Python doesn't have a lot to offer you, especially compared to Rust's compiler. You pretty much just have OOP design principles and, for some classes of null check, mypy (or similar). If you post some examples later I will give you my $0.02 on them, you're ultimately the best person here to make the call though. Sometimes optional int is better than VerboseEncapsulatingTypeHierarchy.
|
# ¿ Oct 10, 2022 22:59 |
|
eXXon posted:Why does it make you nervous? It's less efficient to do key in dict followed by dict[key] if you actually need the value later on. It's also painful to write some comprehensions using dicts without walrus and get. Think QuarkJets did a good job tackling the other cases, but this one is just personal preference from me: any time I'm using a raw dict, I want the "raise if accessing missing key" behavior of the subscript notation. Submitting a PR with .get(key, default) on a raw dict is a yellow flag for me because: Why don't we know if the key will be in there? And, how are we certain that the default value is acceptable in all cases, if we don't even know what keys are in there? Why does this function own the default value of a key instead of the dict constructor? Sometimes it's fine, or you're working in an ecosystem where it's idiomatic to do this kind of stuff. That's fine, I'm not going to try and change e.g. django documentation from this thread. Speaking generally, if this is code your team owns, IME dict.get([...], default) is a canary signal for "something is wrong here and will get worse later". WRT efficiency, I have not yet worked in a python codebase where we can't afford the extra O(1) complexity of performing an explicit "k in d", but I could be convinced to approve such a PR in a codebase that needed it.
|
# ¿ Oct 11, 2022 17:44 |
|
Worth noting that Python has a pretty good interactive experience, right out of the box. If I run your code:Python code:
12 rats tied together fucked around with this message at 20:53 on Nov 2, 2022 |
# ¿ Nov 2, 2022 20:50 |
|
QuarkJets posted:ITT I saw a good video posted about the pitfalls of OOP, it was a talk by this woman who I think was a Ruby guru? Does anyone else remember this? I feel like I'd like to watch it again, it was very good Ruby guru + woman sounds like Sandi Metz, who I have posted about ITT, but she is pro-OOP in the form of Alan Kay's "OOP is mostly message passing", and against the improper use of inheritance. The video I always link is from a talk she does called "nothing is something", and it is very good. The talk is basically an example of inheritance gone wrong, how to recognize it, and how to fix it. https://www.youtube.com/watch?v=OMPfEXIlTVE Apologies if this is not what you were thinking of.
|
# ¿ Nov 14, 2022 19:20 |
|
To pass parameters to a function, you include them in the parenthesis that indicate to Python that you would like to call the function. so, in the REPL, Python code:
When you call "dir()" like that, it's just examining the current local scope. I would guess that there exists a "json" label in this scope because you've imported the json module. To have "dir()" inspect an object, you need to feed it a label that points to that object, which you do by including the label in the parenthesis. The official documentation (above link) is a good source for this and should help clear up anything else you run into as well. 12 rats tied together fucked around with this message at 22:47 on Jan 6, 2023 |
# ¿ Jan 6, 2023 22:01 |
|
the trick here is that python's split method splits by "one or more" blank space characters, just in case you ever had to do this yourself, you could write a loop that iterates through the string and finds "the first instance of the character to split on", and then just keep iterating forward until you find something else. this is usually a lot easier than hoping that e.g. string index number 21 is the start of the next item.
|
# ¿ Jan 19, 2023 02:05 |
|
Data Graham posted:Yeah, I think that's how I think of it — just because Python isn't strongly typed doesn't mean you shouldn't impose contracts on your code yourself (e.g. with type hinting). Which means your function should only do one of two things: a) return two things, or b) raise an exception. Otherwise the calling code has to concern itself with all the weird possibilities of things the function might return, which defeats the whole purpose of factoring complex logic into simple callable methods. Python is strongly typed but it's also dynamically typed - a label can point to a thing that is a different type than what it pointed to previously. Type systems have a lot of dimensions and they can get pretty confusing, for example, python is also "gradually typed" these days, to some degree it is "structurally typed" due to Protocols and also "duck typed". But yes, you should absolutely use type hints when they matter or increase the readability of a particular section of code. Good, relevant example here is tuple unpacking: Python code:
|
# ¿ Jan 20, 2023 22:09 |
|
zipapp (standard library, official python website), shiv, and pex are the things to google if you want to get started packaging python applications with their dependencies
|
# ¿ Jan 23, 2023 18:24 |
|
tqdm is fine. if you had to start from scratch, asyncio is pretty good these days
|
# ¿ Jan 23, 2023 20:23 |
|
dictionary dispatch is a great pattern. if you're on a newer version of python (3.10+) you also have structural pattern matching. you should totally give this whole doc a read through, but this snippet in particular is especially relevantPython code:
i'd probably still start by implementing dictionary dispatch, it seems like a much better fit for your current problem set of "how do I translate user input into a known-safe thing", but if you're writing user tools you should definitely check out the above link which has "handling user input" as a center-stage feature of the tutorial and examples.
|
# ¿ Feb 5, 2023 03:49 |
|
student_grades['Andrew'][4] will get you that list item if you want to loop through each item in the dictionary, the official docs have some guidance: https://docs.python.org/3/tutorial/datastructures.html#looping-techniques
|
# ¿ Feb 23, 2023 18:34 |
|
Everything in itertools is delightful. Basically a standard library module tailor-made for trivializing coding interview screens.
|
# ¿ Mar 1, 2023 07:52 |
|
assuming those "x" are multiplication i would guess you're supposed to realize that multiplication is commutative and that modulus isn't (?), so the way to maximize the value of U is to maximize the result of 1 % arr[n]. which seems weird because 1 % x is either going to be a 0, a 1, or a negative number. if you have two negative numbers you want to get the largest negative number you can out of it, otherwise, you want the smallest. if you have zero negative numbers you just want to make sure arr[n] is nonzero, i guess? weird question
|
# ¿ Mar 23, 2023 17:10 |
|
a dingus posted:If Im understanding correctly maybe NewThing would be better off as a new type which is composed of Thing instead of inheriting it. Agree with this, had half a reply typed out but cancelled it because I was phone posting. From the examples/text posted it seems like there is just Thing and it has one of two different types of UpdateBehavior, so I would model it like that, making sure that I understand fully what the difference is between the UpdateBehaviors is and that I name them after it instead of having OldUpdateBehavior and NewUpdateBehavior.
|
# ¿ Mar 29, 2023 22:45 |
|
WSL is pretty good but most of the "pretty good" is how easy it is to hook into vs code, so you just open code and your linux vm is sitting there in the integrated terminal waiting for you. It's probably also fine with PyCharm, but I've never used it so I can't vouch.
|
# ¿ Apr 1, 2023 21:45 |
|
SSH is extremely good. another neat library in the realm of "python and ssh" is mitogen
|
# ¿ May 4, 2023 18:00 |
|
I think I would probably model that asPython code:
|
# ¿ Aug 9, 2023 05:19 |
|
you could also define data_display inside main's scope. which is not usually recommended but is sometimes a useful pattern
|
# ¿ Sep 13, 2023 22:19 |
|
1. pick 2 delimiters: one for key+value and one for element. split, split, assign. 2. use a markup language. yaml toml and json all allow mappings to be expressed in a single line. toml comes included in python but yaml is likely the most human readable. make sure to read the documentation for your yaml library because it does some type inference that might be surprising to you.
|
# ¿ Nov 6, 2023 18:46 |
|
Your file is really just bytes. Python's `open()` function has configuration for how it should try to interpret the file -- if it should decode the bytes into strings / "words" or if it should just treat each line as bytes. The way to configure this is described here. If you did not specify binary mode, python is reading bytes off of the file system and doing this:quote:[...] in text mode (the default, or when 't' is included in the mode argument), the contents of the file are returned as str, the bytes having been first decoded using a platform-dependent encoding or using the specified encoding if given. As saintonan mentioned, Python is dynamically typed, so however you read the file you're free to convert the data from it into whatever type you need. You can tell what kind of a thing you have by feeding it into `type()`. You can cast a thing to a different type by feeding it into the built-in function for that type, for example, int(), str(), float(). Variables aren't really declared with a type either. A variable's name is just a label that gets attached to an object that lives in memory. The objects have the type, not the labels. Be careful that you don't misinterpret re-assigning a label as mutating an object: Python code:
|
# ¿ Nov 29, 2023 21:38 |
|
Windows has scheduled tasks, linuxes will have cron. You would need a way to tell your scheduled script that a file has already been processed and should not be processed again (maybe move it out of your to-do folder if it successfully produces output). There are thousands of ways to try and solve this problem but given that you're asking here, and considering the language you used to ask about it, I would probably start with scheduled tasks or cron. A piece of advice I would offer is to run your automation against a copy of the data at first, even if you have to manually copy it. It's easy to accidentally break files.
|
# ¿ Dec 13, 2023 19:41 |
|
pyenv + pyenv-alias plugin for isolated installs per project
|
# ¿ Jan 22, 2024 01:32 |
|
I would probably build a lookup table of symbol to function and then use some combination of operator.methodcaller / operator.attrgetter to call them explicitly after parsing the text. This seems like a bad idea, but I'm sure you know that already.
|
# ¿ Jan 26, 2024 19:13 |
|
I used pex for a thing and I liked it. We ended up shelving it and writing a rust version of the tool instead, and if we need to do more stuff in this area later, I have "try nuitka" on my todo list.
|
# ¿ Feb 14, 2024 22:13 |
|
basically if you have to descend into a function because you didn't know it existed, that's fine, but if you have to bring something from inside it with you and then continue your search, it shouldn't have been a function
|
# ¿ Feb 28, 2024 00:20 |
|
it depends but short answer probably not. if you wanted it to be accessible on that network you'd want to run it bound to an IP address in that network. if pycharm, specifically, binds to 127.0.0.1, it's not routable, since that means "local computer" and it's ~not possible for a packet to arrive at your computer with that destination address. if pycharm binds to 0.0.0.0 you can still access it through 127.0.0.1, but it would also be accessible on other addresses, which means it could theoretically be routed to you, which means it could theoretically be accessed by another device in that network. (if nothing blocked it first, like a firewall)
|
# ¿ Mar 13, 2024 01:42 |
|
|
# ¿ May 15, 2024 19:06 |
|
I would say to use pyright over mypy these days. Also re: `list` vs `list[str]`, if you have a list of things that aren't all the same type, but they should all have some method, the thing for describing that is protocols. You have a list[Sendable], or list[CanSend], or something like that.
|
# ¿ Mar 23, 2024 01:35 |