[HN Gopher] Fastcore: A library that extends Python with new fea...
       ___________________________________________________________________
        
       Fastcore: A library that extends Python with new features
        
       Author : thenipper
       Score  : 132 points
       Date   : 2020-09-04 13:29 UTC (1 days ago)
        
 (HTM) web link (fastpages.fast.ai)
 (TXT) w3m dump (fastpages.fast.ai)
        
       | karlicoss wrote:
       | Nice work! It's often hard to communicate complexity and justify
       | the abstractions, but nevertheless it's a cool demonstration of
       | what's possible in Python. It's worth thinking about simplifying
       | code and DSLs, as long as you don't go too crazy.
       | 
       | My personal concern would be the lack of typing annotations (IMO
       | very important to have in a 'standard library'), and even if they
       | were present I doubt something like `store_attr()` would be
       | typeable without a mypy plugin.
       | 
       | Personally, I sometimes trade boilerplate and tolerate code
       | duplication for the sake of the code being transparent to static
       | analysis.
        
       | orf wrote:
       | I dislike some of these. Some are cool, like 'Self', but giant
       | "swiss army knife" libraries feel odd.
       | 
       | > Avoid boilerplate when setting instance attributes
       | 
       | dataclasses[1]
       | 
       | > Type Dispatch
       | 
       | functools.singledispatch works with type annotations[2]
       | 
       | > A more useful __repr__
       | 
       | dataclasses[1]
       | 
       | > A better pathlib.Path
       | 
       | path_object.read_text()[3]. The pickle stuff is interesting, but
       | I don't see the value over just pickle.load(path_object).
       | Monkeypatching Path to add this fees odd and unpythonic.
       | 
       | 1. https://docs.python.org/3/library/dataclasses.html
       | 
       | 2.
       | https://docs.python.org/3/library/functools.html#functools.s...
       | 
       | 3.
       | https://docs.python.org/3/library/pathlib.html#pathlib.Path....
        
         | formerly_proven wrote:
         | Using pickle for "Path.save/load" feels like a shortcut to me
         | that is inappropriate for many circumstances, since loading a
         | pickle in Python literally means running code from that pickle.
         | It's basically eval(Path.read()). It's not the kind of trust
         | relationship that I would typically expect from a load/save
         | pair.
         | 
         | > Wait! What's going on here? We just imported pathlib.Path -
         | why are we getting this new functionality?
         | 
         | If you are writing a library and this is part of your expose,
         | think long and hard.
         | 
         | > Path.ls
         | 
         | Highly gimmicky, doesn't support globs. Arguments are "n_max,
         | file_type and file_exts", in that order. n_max seems largely
         | pointless for real programs and like a workaround for a poor
         | REPL for interactive use. The difference between the last two
         | arguments is that the first one also accepts mimetypes (does
         | this call "file" on every file it sees?).
         | 
         | Arguably the signature of a "Path.ls" should rather look like
         | "Path.ls(glob='<star>', <star>, files=True, dirs=True)" and it
         | should probably not return a bunch of strings.
        
           | jph00 wrote:
           | Look closer. It doesn't return strings.
        
         | jph00 wrote:
         | I'm the author of fastcore.
         | 
         | dataclasses is not very extensible or flexible. It's fine for
         | starting with, but it's not at all a replacement for store_attr
         | etc.
         | 
         | At fast.ai we used dataclasses extensively for a couple of
         | years, but it just kept biting us. So eventually we switched to
         | these different approaches, which have worked much better for
         | us.
         | 
         | singledispatch is nice enough too, but multiple dispatch with
         | typedispatch is fat more flexible and powerful.
         | 
         | Just because something is in the stdlib, doesn't mean it's the
         | perfect solution to every problem, and that everyone should try
         | to hack their code to fit into those existing solutions.
        
           | nemetroid wrote:
           | > dataclasses is not very extensible or flexible. It's fine
           | for starting with, but it's not at all a replacement for
           | store_attr etc.
           | 
           | > At fast.ai we used dataclasses extensively for a couple of
           | years, but it just kept biting us.
           | 
           | What were the issues you had?
        
             | jph00 wrote:
             | The key issue is that it requires inheritance, but doesn't
             | actually support subclassing very well.
             | 
             | Also it relies on python's type system, which is rather
             | limited.
             | 
             | It's a very large module for what it does, and
             | understanding all the details of how it works in practice
             | is a big challenge.
        
             | Recursing wrote:
             | https://www.attrs.org/en/stable/why.html#data-classes
             | 
             | The most used python library for these things is attrs, I
             | think it mostly provides support for slotted classes (more
             | memory efficient), "converters" (normalization), validation
             | and serialization
        
         | ghj wrote:
         | I didn't know about
         | functools.singledispatch/singledispatchmethod, that looks
         | really nice!
         | 
         | For typing hinting, I've been annotating with @overload which
         | is just god awful ugly. And you still need to switch based on
         | instance type for the actual implementation.
         | 
         | I will try this way instead!
         | 
         | [1] https://www.python.org/dev/peps/pep-0484/#function-method-
         | ov...
        
         | pbsds wrote:
         | I agree on the monkeypatching of pathlib. It makes it difficult
         | for a reader to look up what the functions do. Providing a
         | different module, like `import nPathlib as Pathlib` would be a
         | lot more discoverable.
        
           | jph00 wrote:
           | Your coding environment really should be providing that basic
           | functionality for you.
        
         | ebg13 wrote:
         | > _functools.singledispatch works with type annotations[2]_
         | 
         | Only for the first argument. "Note that the dispatch happens on
         | the type of the first argument, create your function
         | accordingly".
         | 
         | Making delegated kwargs transparent is 100% cool though and
         | addresses a huge problem with delegated interfaces. I'd use
         | that all the time.
         | 
         | I agree with you about the swiss army thing. I wish it weren't
         | bundled with all this other stuff.
        
       | codegladiator wrote:
       | > Whenever I see a function that has the argument __kwargs, I
       | cringe a little
       | 
       | I cringe a little when someone says a straight forward thing
       | should be replaced by magic middleware.
        
       | lacker wrote:
       | This library reminds me of fast.ai itself. It's cool how you can
       | do so many things with a few lines of code, and I was impressed
       | the first couple times I used it. Over time, I started to run
       | into problems when I wanted to do something beyond the initial
       | demo. Many parameters are undocumented, functions do something
       | automatically that's often nice but there's no clear way to undo
       | it, and side effects are scattered about. I would prefer code
       | that was slightly longer, but simpler and more pythonic.
        
       | fpgaminer wrote:
       | Love the fast.ai ecosystem.
       | 
       | Most don't appreciate how critical it is for an ML researcher to
       | be able to play. The best research in fields like that require a
       | tight feedback loop, since we lack an intuition or logical
       | framework from which to reason about these systems. Instead we
       | have to throw shit at the wall, inspect what sticks, and repeat
       | 1000x. The vast majority of evolutionary leaps that I've seen in
       | ML and fields like it have been from "stupid" stuff no classic
       | researcher in their right mind would try. Instead it arises out
       | of a sense of curiosity and playing around. "I wonder what would
       | happen if we used only attention layers? Wouldn't that be silly?"
       | ...
       | 
       | Tooling is a huge part of that. The cost of iterating needs to be
       | low. If you have to rebuild your entire training loop to try a
       | stupid idea, you're not going to try that idea. That's what makes
       | ecosystems like fast.ai so valuable. The whole thing is designed
       | for fast, cheap, highly malleable iteration.
       | 
       | The design decisions required to achieve that have resulted in a
       | library with its fair share of sharp corners. It's a bit of a
       | holographic codebase, where functionality is splintered all
       | across the surface of it. The focus on Notebooks and code jamming
       | leave engineering traditionalists wanting. Etc.
       | 
       | Don't get me wrong. When I write write most other code, I put my
       | engineering glasses on. I want code to be clear and transparent,
       | maintainable, idiomatic, etc. It's just that in ML play is more
       | critical.
       | 
       | So it's important to look at fastai's codebase through that lens.
       | I disagree with commenters here criticizing the codebase as being
       | akin to what an inexperienced engineer would write. Instead it's
       | clear to me that the fastai developers have made numerous very
       | conscious decisions to break convention in support of their
       | goals. They've done that well. And I think it's all in support of
       | their "fast" ideal.
       | 
       | Honestly if I were to lob real criticism at fastai, it would be
       | to say that it needs more documentation. I know, that's a weird
       | criticism given their use of literate programming and the courses
       | available. But ... for example, I have such a hard time with the
       | DataBlock API. I didn't come out of the courses with a good
       | understand of it and the docs are IMO too lacking to sufficiently
       | teach an intuition about it. I had a model where the "y" variable
       | is generated by the model itself. Was never able to figure out
       | the idiomatic way to express that in fastai. Had to fight the
       | DataBlock API and the training loop system tooth and nail to fit
       | it in. I'm sure there's a way to do it. It just wasn't apparent
       | to me.
       | 
       | Of course, that's a _criticism_, not a complaint. The work of
       | Jeremy and co is just an incredible gift to the world. I don't
       | think it speaks ill to say the docs are lacking. That's true of
       | the vast majority of open source software. Documentation is plain
       | _hard_. And the courses, while they touch on the library a good
       | amount, are primarily focused on teaching ML concepts ... as they
       | should be.
       | 
       | Hell, I bet they are aware of that and their switch to literate
       | programming is probably driven by it. It's probably just early in
       | that cycle and things will continue to get better.
       | 
       | I hope it's clear this comment is more about love of the library
       | than a complaint about what is otherwise an amazing thing.
        
       | typon wrote:
       | This library reminds me a lot of the code I've seen from junior
       | developers trying to make things "cool" by removing a few
       | characters of typing in exchange for library abstractions that
       | create headaches down the line. I think features like this take
       | years to naturally evolve in a codebase, on an as needed basis.
       | And once that code base has evolved to reach something resembling
       | non idiomatic Python, it can be quite hard to integrate new devs
       | into the team. Such transitions into custom dsls or nifty tools
       | are inevitable for large code bases, but I try to minimize it as
       | much as possible, even when it hurts productivity. Long term
       | maintainability is more important to me.
        
         | digitallogic wrote:
         | > I try to minimize it as much as possible, even when it hurts
         | productivity. Long term maintainability is more important to
         | me.
         | 
         | I don't think this needs to be an either/or choice in these
         | situations. You can have both if you make the make the
         | conscious decision to not fight your tools. Yes, sometimes you
         | have to be more verbose in one language than another, but the
         | productivity hit in that case always pales in comparison to the
         | hours, days, and in some cases I've seen, weeks, lost by
         | someone fighting their language/tools.
         | 
         | My favorite example of this was a developer given a 2 week
         | feature implementation that ballooned to two months. They had
         | minimal experience C++, and they didn't like its looping
         | syntax. Rather than accept that frustration and write the code
         | in a syntax they disliked, they instead spent weeks writing a
         | "re-usable library that abstracts away looping semantics".
        
         | slaymaker1907 wrote:
         | I know what you are talking about in general, but most of the
         | stuff in this library seems to either add clarity or help
         | prevent errors. The problem of kwargs where you end up with a
         | bunch of confusion on documentation is definitely a real thing.
         | 
         | Multiple dispatch is also a great thing as well. You don't
         | realize you need it until you try implementing something
         | unification algorithm.
         | 
         | Compose is nice for reducing the mental overhead of reading
         | nested expressions. However, I do wish they took a line from
         | lodash and implemented flow instead (like compose but reversed
         | so the first argument is invoked first, then the output of that
         | is fed into the second, and so on).
         | 
         | Syntactic sugar is not bad if it increases signal to noise when
         | reading code or if it prevents erroneous usage.
        
           | marmaduke wrote:
           | Ok but what's with the pre post meta init thing? Let's see a
           | junior run a debugger through that! Dropping one line of code
           | costs several stack frames in your debug session.
        
             | jph00 wrote:
             | It's a feature from the standard library. However it's only
             | normally available in dataclass. fastcore simply brings the
             | same functionality to other classes too.
        
         | hitekker wrote:
         | I have a feeling these Python enhancement libraries will become
         | ever more popular now that Guido has stepped down.
         | 
         | I wonder what the vision of Python's steering committee is.
        
         | GhostVII wrote:
         | Lot of the features in this library seem to be targeted at
         | making things clearer, not just making your code as compact as
         | possible. It is a lot cleaner to use type dispatch rather than
         | have some switch case in your function to determine behavior.
         | And it is useful to know where the kwargs is being used rather
         | than have it be a black box. Having to store every parameter
         | from __init__ into self is an annoying pattern I find myself
         | almost always following, so it's nice to have a solution to
         | that too.
         | 
         | Generally I prefer to use vanilla python as much as possible,
         | but I think there is value in having libraries like this, which
         | make things clearer and have less boilerplate without much
         | cost. Most of what I see would be pretty easy to replace with
         | regular python if you decided to move away from the library,
         | there aren't lots of wierd layers being added to your code.
        
         | giancarlostoro wrote:
         | I think the sweet spot is the approach taken by Kotlin for
         | making DSLs because it further removes ceremonial boilerplate
         | that Java loves to give you. I think Pythons as minimalist as
         | it needs to be... The best I do is rename imports that are long
         | if anything. I also define function pointers if I reuse the
         | same method call throughout a tree which helps to keep things
         | tight yet still readable.
        
         | wirthjason wrote:
         | I've seen this happen with senior devs too, but who come from a
         | background other than Python.
         | 
         | There's a lot of value in deeply learning the internals of a
         | language so you can write good code in the target language
         | rather than developing some mashup of "features".
         | 
         | Ironically the article begins with be premise of deeply
         | learning python but never touches on the advanced features that
         | were learned and applied to develop the library.
        
           | jph00 wrote:
           | The person that wrote the article doesn't work at fast.ai and
           | didn't write the library, so they don't have that
           | information.
        
             | hitekker wrote:
             | But aren't you one of the authors of this article? The
             | headline lists you as an author and you're a founding
             | researcher at Fast.ai.
        
               | jph00 wrote:
               | Oh so it does! Sorry I'll ask Hamel to change that - he's
               | just being generous with his credit. I didn't write a
               | single word of it!
               | 
               | Sorry for the confusion. :)
        
               | mloncode wrote:
               | Sorry about that. Indeed, I felt that since he was the
               | author of the library and essential to me learning it I
               | felt the least I could do was to put his name on there. I
               | removed his name via
               | https://github.com/fastai/fastpages/pull/408 -- Sorry for
               | the confusion!
               | 
               | Indeed, even though I learned a ton about python, I
               | didn't feel like what I had to say made for an
               | interesting blog article, and was a bit abstract. I was
               | equally excited about the library from and end user's
               | perspective and decided to blog about that instead.
        
         | wrkronmiller wrote:
         | There used to be a saying among web developers that you can
         | either use a framework or end up building a framework.
        
         | [deleted]
        
         | ayush--s wrote:
         | All sizable codebases eventually grow their own patterns &
         | utils that have similar abstractions. I'd rather spend my time
         | writing business logic than boilerplate.
        
       | bonoboTP wrote:
       | Too clever, too much magic. I remember I used to create such
       | things in my projects in my earlier days as a dev and was quite
       | proud of how compact things were and how much I understand my way
       | around the language that I was able to come up with it. But at
       | the end of the day, these things have a much higher price than it
       | seems at first. Sparing a few lines here and there is not worth
       | confusing your code's readers or yourself in a year. Standard
       | established "pythonic" solutions are preferable.
       | 
       | Some are nice functions, I guess all of us have our collection of
       | utils that we carry around projects and it's certainly nice to
       | have some of them collected in an installable library. But I'd
       | prefer to have them separately in small, separately installable
       | modules, similar to "more_itertools".
       | 
       | delegates: Maybe it's useful for auto-completion in notebooks.
       | 
       | store_attr(): Too confusing.
       | 
       | Avoiding subclassing boilerplate: don't, it's too confusing. Type
       | dispatch: perhaps, but I think isinstance is okay too.
       | 
       | A better version of functools.partial: Ok, docstring is kept.
       | Could be even changed in the standard library.
       | 
       | Composition of functions: Okay, could be an addition to functools
       | in the standard library.
       | 
       | A more useful __repr__: Good.
       | 
       | Monkey Patching With A Decorator: Please don't.
       | 
       | A better pathlib.Path: I don't think loading pickle should be a
       | method of Path objects. I already dislike pathlib putting
       | read_text as a method of Path. Why not Path.read_jpeg_image()?
       | Path.save_mp4_video() etc. Also don't monkey patch Path please.
       | 
       | Self: too confusing, little upside to it. It makes things look
       | like the function is being called, while actually only a lambda
       | is produced. Too much magic.
       | 
       | in_notebook(), in_colab(), in_ipython: Useful.
       | 
       | The L list: the numpy style indexing is nice, but you may as well
       | create a numpy array.
        
       | [deleted]
        
       | miguendes wrote:
       | > Wait! What's going on here? We just imported pathlib.Path - why
       | are we getting this new functionality? Thats because we imported
       | the fastcore.foundation module, which patches this module via the
       | @patch decorator discussed earlier.
       | 
       | This is a recipe for disaster. Too much magic that makes it
       | harder to debug. Especially for junior developers or people less
       | experienced in python.
       | 
       | I've seen fast.ai code and in terms of good practices it violates
       | a bunch for the sake of convention. A good example is the `from
       | module import *`.
        
         | jph00 wrote:
         | That's not a good example at all.
         | 
         | Every fast.ai module defines __all__, and is carefully designed
         | to allow "import *" to be used safely. I'm not aware of any
         | other library that goes to this trouble.
        
           | kyran_adept wrote:
           | Not having _all_ is just part of the problem. With "import *"
           | you also unknowingly load and potentially overwrite symbols.
           | If you specify each symbol you use, it's very simple for even
           | the most basic linter to figure you are doing something
           | wrong.
        
             | jph00 wrote:
             | It's not unknowingly at all.
        
           | mkolodny wrote:
           | Allowing import \\* to be used safely in notebooks is one
           | thing. Using it in a library is very different.
           | 
           | import \\* is convenient to use in a shell. But it makes code
           | more difficult to read. If code doesn't explicitly say where
           | variables were imported from, it takes extra time to figure
           | out where variables were imported from - especially if you're
           | reading code on GitHub.
        
             | jph00 wrote:
             | On GitHub you can click the symbol to see where it comes
             | from. Any decent editor should provide similar
             | functionality.
             | 
             | Reading the import line to find where a symbol comes from
             | is really clunky.
        
               | orf wrote:
               | It's not reading the import line. It's reading
               | "requests.get(...)" instead of "get(...)"
        
               | greatgib wrote:
               | I hope that it will not look like a personal attack but,
               | honestly, without looking at fastai, your replies on this
               | comment thread does not let me think that the library is
               | of very good quality.
               | 
               | I see there the typical pattern of the 'expert beginner'
               | developer.
               | 
               | If you read yourself,you are saying that you know well
               | that it is better to rely on a specific platform (Github)
               | or editor to be able to resolve your mess than having
               | self descriptive/sufficient code...
               | 
               | For the module using a library, when you do an 'import *'
               | it can easily create a very big mess. For example, as a
               | dev you see a piece of code and you don't necessarily
               | know where all the symbols come from and so the
               | associated dependencies. And so if you have to move this
               | piece of code to another place you can have a hard time
               | to ensure and fix imports on the other side to be sure
               | that it matches.
               | 
               | I'm sorry if I'm not clear, but it is so wrong on so many
               | points in an obvious way that I don't even know what to
               | start with.
        
       | armitron wrote:
       | I didn't find a single thing that I liked here.
       | 
       | Rather, I thought these syntactic layers made things worse rather
       | than better, in terms of clarity, understandability and ease of
       | writing simple, straightforward code.
        
       | [deleted]
        
       | LukeB42 wrote:
       | All libraries extend their language with new features.
       | 
       | A lot of the proposed value-add seems like the authors aren't
       | aware the built-in `type()` can dynamically modify class
       | definitions.
       | 
       | Getting rid of `hex(id(self))` in `__repr__` is regressive UX.
       | 
       | @typedispatch seems like both a slow way of using 'isinstance()'
       | and a FOMO C++ virtual function bloat.
        
         | qayxc wrote:
         | What does typed dispatch have to do with virtual functions in
         | C++? This type of dispatch happens at compile-time in C++ and
         | has nothing to do with "bloat" or even virtual functions.
        
       | Galanwe wrote:
       | Not sure if this is an elaborate prank or a real attempts at
       | making Python more Java like.
       | 
       | I stopped reading when the author suggests using
       | 
       | class NewParent(ParentClass, metaclass=PrePostInitMeta): def
       | __pre_init__(self, _args,_ *kwargs): super().__init__()
        
       | hansvm wrote:
       | Some of this looks excellent. E.g. I occasionally add features
       | like the kwargs delegate in my own code, and there are plenty of
       | places in scipy where that would be an improvement.
       | 
       | Other bits of it aren't drastically better than the standard
       | library. Their typeddispatch is undeniably useful, but
       | functools.singledispatch covers most use cases, and it'd be a
       | shame to pull in all of fastcore for a single feature that's
       | probably covered by another library (e.g. the multipledispatch
       | library).
       | 
       | Some of this is horrifying. There's nothing wrong with the
       | PrePostInitMeta per se....but I guarantee that's going to be a
       | footgun down the line, and IMO if somebody isn't able to
       | comfortably write that metaclass themselves they probably
       | shouldn't be using it.
        
         | olejorgenb wrote:
         | @delegate would be very neat if IDEs understood it.
         | Unfortunately doesn't seem to be the case for pycharm.
        
           | hansvm wrote:
           | Agreed (though it should still work with tooling like Sphinx
           | and would definitely work in a REPL, notebook, or debugger).
           | 
           | That touches on a slightly bigger issue too. IDEs only
           | approximate the language and usually fail miserably if you,
           | e.g., do anything nontrivial with PEP-263. They'll whine when
           | new language features like async or assignment expressions
           | come out, they have the damnedest time inferring the type of
           | inner functions, and so on. An IDE typically offers support
           | for a (hopefully useful) subset of your favorite language.
        
         | jph00 wrote:
         | PrePostInitMeta is just adding what's already in the stdlib
         | dataclasses, but making it available to other classes too.
        
           | hansvm wrote:
           | Agreed (mostly...it looks more powerful than dataclasses
           | afaict). It looks like it could have a ton of use cases.
           | 
           | My concern is that it seems easy to get started, but
           | metaclass hackery is hard to get right if you do much of it.
           | Maybe that fear is unfounded; have you found that people tend
           | to use it responsibly?
           | 
           | As a small side-note, on the surface I'm not seeing any
           | reason it couldn't be implemented with something more
           | composable like __init_subclass__, and that might be a nice
           | touch.
        
           | nemetroid wrote:
           | Dataclasses have __post_init__, but they don't have a
           | __pre_init__, do they? From what I can tell, PrePostInitMeta
           | adds a completely new __dunder__ method with pre_init.
        
       | rzimmerman wrote:
       | I actually think the "delegates" syntax for kwargs or something
       | like it is worth adding to the standard library. The rest feels
       | like it's either covered by dataclasses or not something I
       | personally want in python. Except pre_init and post_init instead
       | of calling super().__init__. But that's up there with if __name__
       | == "__main__" for being an annoying idiosyncrasy that's too hard
       | to change.
        
         | ayush--s wrote:
         | There is functools.wraps in standard library for similar
         | "delegation" in decorators
        
       | linkdd wrote:
       | Monkeypatching anywhere except unittests is a nono for me. It
       | adds some black magic you need to know before reading the code.
       | 
       | Am I reading the standard pathlib.Path or the monkeypatched one ?
       | If I have a bug with it, it comes from the standard library or
       | the patch introduced silently ?
       | 
       | Remember the zen of Python:
       | 
       | > Explicit is better than implicit
       | 
       | And I would personally prefer a unification library (
       | https://github.com/mrocklin/unification/ ) over the type dispatch
       | proposed here. It's just more powerful and closer to pattern
       | matching if that's really what you want.
        
         | BiteCode_dev wrote:
         | Same.
         | 
         | But I think what they did with partial should be in the stdlib.
         | 
         | In fact partial should also be rewritten in C et promoted to
         | built in.
         | 
         | Right now it's 10 times slower than lambda, and you have to
         | know about and wish to import functools, yet still loose the
         | docstring.
         | 
         | Shame for such a great feature.
        
           | wrmsr wrote:
           | As far as I can tell functools.partial has been implemented
           | in C since it was added sixteen years ago ( https://github.co
           | m/python/cpython/commit/9c323f8de4910dfc0ba... ), and it's
           | faster than lambda ( https://gist.github.com/wrmsr/1e13eda3ed
           | 78288679c010acbe6d2b... ). Regarding docstrings you can
           | access the underlying function via the __wrapped__ attribute,
           | and signature forwarding is too brittle and magical for
           | stdlib.
        
         | Alex3917 wrote:
         | > Monkeypatching anywhere except unittests is a nono for me.
         | 
         | What do you think about adding pprint to builtins so that you
         | don't need to import it each time when debugging? (Or,
         | alternatively, so that you don't need to add it to the top of
         | every single file?) It seems kind of wrong, but the
         | alternatives are bad also. I'm not sure why Python didn't do
         | this themselves when they added breakpoint in 3.7.
        
           | kristjansson wrote:
           | Pdb already has pretty print built in?                   $
           | python -m pdb ...         (Pdb) help pp         pp expression
           | Pretty-print the value of the expression.         (Pdb) pp
           | ...
        
           | linkdd wrote:
           | The debug code you add doesn't get removed before going into
           | production?
        
           | orf wrote:
           | pprint is a standard library module which isn't necessarily
           | available everywhere. You can run python without the standard
           | library, but the moment you add it to the default builtins it
           | needs to become part of the language.
        
           | lacker wrote:
           | Monkeypatching in one application is maybe okay. You really
           | want pprint in builtins, fine, who is it really hurting?
           | 
           | Monkeypatching in a library like fastcore that many other
           | people use is really bad. All sorts of bugs and
           | incompatibilities will happen down the road, as software
           | becomes dependent on your monkeypatch without anyone
           | realizing it.
        
           | xapata wrote:
           | Can you configure your debugger to include it? I'd rather do
           | that than modify production code to include a debugging tool.
        
       | kristjansson wrote:
       | Fastai/Fastcore are fascinating in their emphasis on interactive
       | computing in notebooks. I think that starting from the assumption
       | that users will be
       | 
       | (a) primarily using the abstractions in this library
       | interactively
       | 
       | (b) to do analysis, or experiment with many different
       | implementations of similar functions
       | 
       | (c) in long-lived sessions where re-running to the same point may
       | be expensive in time or compute, or impossible due dependence on
       | cell execution order etc.
       | 
       | makes their design choices make more sense to me.
       | 
       | Lots of the functionality identified here sort of nice if you're
       | in a traditional environment, but imperative if you're in (or
       | writing for users in) a notebook environment. For example, the
       | emphasis on preserving propagating signature information in
       | function objects themselves makes sense if you're relying on
       | `inspect` to provide IDE-like autocompletion. The emphasis on
       | easy monkey-patching and psuedo-generics makes sense if you're
       | interactively working with classes in modules you don't control,
       | or can't cleanly reimport.
       | 
       | Not only that, fastai/fastcore themselves are written in Jupyter
       | notebooks via their literate programming environment nbdev [1]!
       | 
       | I don't know that there's a point here beyond a bit of begrudging
       | admiration for how far they've pushed the notebook platform. It
       | makes for a library (and a Python) that looks and feels just a
       | few degrees off-axis from much of the rest of the ecosystem...
       | 
       | [1]: https://nbdev.fast.ai
        
       | vvladymyrov wrote:
       | I hope that fast.ai courses do not and will not use this library
       | - it would increase required effort to understand the code in
       | lessons.
        
         | tmabraham wrote:
         | This is the fastai library used: https://docs.fast.ai/
         | 
         | You don't directly use fastcore for most things, but fastai
         | underneath uses fastcore. If you want to extend fastai for
         | custom and advanced tasks, fastcore is actually very helpful to
         | use.
        
       | heavyset_go wrote:
       | I'm only really a fan of @typeddispatch and the @patch decorator.
       | They don't do anything weird and follow the standard Python
       | decorator pattern.
        
       | pryelluw wrote:
       | Longtime pythonista and co-organizer of PyATL here. I appreciate
       | the goals of the library and understand the points being made in
       | the code. There are certain things that python has acquired over
       | time that are not as nice as they could be. Or maybe we can say
       | that momentum to improve them reduces over time.
       | 
       | One of these things is the __init__ method. It is not named in a
       | clear manner and can be verbose. The alternative proposed with
       | store_attr is close, but still falls to be descriptive. Ideally,
       | I'd just adopt the keyword "constructor" or "initialize" and have
       | it be synthathic sugar for __init__. I do like the fact that it
       | provides a shorter way to initialize things. That could be
       | adopted with no drawbacks as long as we keep named parameters.
       | 
       | I congratulate and welcome such ideas. Ill invite the library
       | author(s) to join the python core team and discuss the ideas with
       | them. It can take time to get new things into a project like
       | python, but we cant grow a language by doing the same thing over
       | and over. Languages need to evolve (to a certain extent) over
       | time.
        
       ___________________________________________________________________
       (page generated 2020-09-05 23:00 UTC)