You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+23-23Lines changed: 23 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
> Python goodies to make your coding faster, easier, and more maintainable
3
3
4
4
5
-
Python is a powerful, dynamic language. Rather than bake everything into the language, it lets the programmer customize it to make it work for them. `fastcore` uses this flexibility to add to Python features inspired by other languages we've loved, like multiple dispatch from Julia, mixins from Ruby, and currying, binding, and more from Haskell. It also adds some "missing features" and cleans up some rough edges in the Python standard library, such as simplifying parallel processing, and bringing ideas from NumPy over to Python's `list` type.
5
+
Python is a powerful, dynamic language. Rather than bake everything into the language, it lets the programmer customize it to make it work for them. `fastcore` uses this flexibility to add to Python features inspired by other languages we've loved, like multiple dispatch from Julia, mixins from Ruby, and currying, binding, and more from Haskell. It also adds some "missing features" and clean up some rough edges in the Python standard library, such as simplifying parallel processing, and bringing ideas from NumPy over to Python's `list` type.
6
6
7
7
## Installing
8
8
@@ -27,7 +27,7 @@ Here's a (somewhat) quick tour of a few higlights, showing examples from each of
27
27
28
28
All fast.ai projects, including this one, are built with [nbdev](https://nbdev.fast.ai), which is a full literate programming environment built on Jupyter Notebooks. That means that every piece of documentation, including the page you're reading now, can be accessed as interactive Jupyter notebooks. In fact, you can even grab a link directly to a notebook running interactively on Google Colab - if you want to follow along with this tour, click the link below, or click the badge at the top of the page:
29
29
30
-
```python
30
+
```
31
31
colab_link('index')
32
32
```
33
33
@@ -37,7 +37,7 @@ colab_link('index')
37
37
38
38
The full docs are available at [fastcore.fast.ai](https://fastcore.fast.ai). The code in the examples and in all fast.ai libraries follow the [fast.ai style guide](https://docs.fast.ai/dev/style.html). In order to support interactive programming, all fast.ai libraries are designed to allow for `import *` to be used safely, particular by ensuring that [`__all__`](https://riptutorial.com/python/example/2894/the---all---special-variable) is defined in all packages. In order to see where a function is from, just type it:
39
39
40
-
```python
40
+
```
41
41
coll_repr
42
42
```
43
43
@@ -64,13 +64,13 @@ fastcore's testing module is designed to work well with [nbdev](https://nbdev.fa
That's an example from the docs for `coll_repr`. As you see, it's not showing you the output directly. Here's what that would look like:
72
72
73
-
```python
73
+
```
74
74
coll_repr(range(1000), 5)
75
75
```
76
76
@@ -87,7 +87,7 @@ So every test shown in the docs is also showing you the behavior of the library
87
87
88
88
Test functions always start with `test_`, and then follow with the operation being tested. So `test_eq` tests for equality (as you saw in the example above). This includes tests for equality of arrays and tensors, lists and generators, and many more:
89
89
90
-
```python
90
+
```
91
91
test_eq([0,1,2,3], np.arange(4))
92
92
```
93
93
@@ -108,28 +108,28 @@ If you want to check that objects are the same type, rather than the just contai
108
108
109
109
You can test with any comparison function using `test`, e.g test whether an object is less than:
110
110
111
-
```python
111
+
```
112
112
test(2, 3, operator.lt)
113
113
```
114
114
115
115
You can even test that exceptions are raised:
116
116
117
-
```python
117
+
```
118
118
def divide_zero(): return 1/0
119
119
test_fail(divide_zero)
120
120
```
121
121
122
122
...and test that things are printed to stdout:
123
123
124
-
```python
124
+
```
125
125
test_stdout(lambda: print('hi'), 'hi')
126
126
```
127
127
128
128
### Foundations
129
129
130
130
fast.ai is unusual in that we often use [mixins](https://en.wikipedia.org/wiki/Mixin) in our code. Mixins are widely used in many programming languages, such as Ruby, but not so much in Python. We use mixins to attach new behavior to existing libraries, or to allow modules to add new behavior to our own classes, such as in extension modules. One useful example of a mixin we define is `Path.ls`, which lists a directory and returns an `L` (an extended list class which we'll discuss shortly):
131
131
132
-
```python
132
+
```
133
133
p = Path('images')
134
134
p.ls()
135
135
```
@@ -143,7 +143,7 @@ p.ls()
143
143
144
144
You can easily add you own mixins with the `patch`[decorator](https://realpython.com/primer-on-python-decorators/), which takes advantage of Python 3 [function annotations](https://www.python.org/dev/peps/pep-3107/#parameters) to say what class to patch:
145
145
146
-
```python
146
+
```
147
147
@patch
148
148
def num_items(self:Path): return len(self.ls())
149
149
@@ -161,7 +161,7 @@ We also use `**kwargs` frequently. In python `**kwargs` in a parameter like mean
161
161
162
162
`GetAttr` solves a similar problem (and is also discussed in the article linked above): it's allows you to use Python's exceptionally useful `__getattr__` magic method, but avoids the problem that normally in Python tab-completion and docs break when using this. For instance, you can see here that Python's `dir` function, which is used to find the attributes of a python object, finds everything inside the `self.default` attribute here:
163
163
164
-
```python
164
+
```
165
165
class Author:
166
166
def __init__(self, name): self.name = name
167
167
@@ -182,7 +182,7 @@ p = ProductPage(Author("Jeremy"), 1.50, 0.50)
182
182
183
183
Looking at that `ProductPage` example, it's rather verbose and duplicates a lot of attribute names, which can lead to bugs later if you change them only in one place. `fastcore` provides `store_attr` to simplify this common pattern. It also provides `basic_repr` to give simple objects a useful `repr`:
One of the most interesting `fastcore` functions is the `funcs_kwargs` decorator. This allows class behavior to be modified without sub-classing. This can allow folks that aren't familiar with object-oriented programming to customize your class more easily. Here's an example of a class that uses `funcs_kwargs`:
201
201
202
-
```python
202
+
```
203
203
@funcs_kwargs
204
204
class T:
205
205
_methods=['some_method']
@@ -225,7 +225,7 @@ Like most languages, Python allows for very concise syntax for some very common
225
225
226
226
On this basis, `fastcore` has just one type that has a single letter name:`L`. The reason for this is that it is designed to be a replacement for `list`, so we want it to be just as easy to use as `[1,2,3]`. Here's how to create that as an `L`:
227
227
228
-
```python
228
+
```
229
229
L(1,2,3)
230
230
```
231
231
@@ -238,7 +238,7 @@ L(1,2,3)
238
238
239
239
The first thing to notice is that an `L` object includes in its representation its number of elements; that's the `(#3)` in the output above. If there's more than 10 elements, it will automatically truncate the list:
240
240
241
-
```python
241
+
```
242
242
p = L.range(20).shuffle()
243
243
p
244
244
```
@@ -252,7 +252,7 @@ p
252
252
253
253
`L` contains many of the same indexing ideas that NumPy's `array` does, including indexing with a list of indexes, or a boolean mask list:
254
254
255
-
```python
255
+
```
256
256
p[2,4,6]
257
257
```
258
258
@@ -265,7 +265,7 @@ p[2,4,6]
265
265
266
266
It also contains other methods used in `array`, such as `L.argwhere`:
267
267
268
-
```python
268
+
```
269
269
p.argwhere(ge(15))
270
270
```
271
271
@@ -280,7 +280,7 @@ As you can see from this example, `fastcore` also includes a number of features
280
280
281
281
There's too much functionality to show it all here, so be sure to check the docs. Many little things are added that we thought should have been in `list` in the first place, such as making this do what you'd expect (which is an error with `list`, but works fine with `L`):
282
282
283
-
```python
283
+
```
284
284
1 + L(2,3,4)
285
285
```
286
286
@@ -295,7 +295,7 @@ There's too much functionality to show it all here, so be sure to check the docs
295
295
296
296
Most Python programmers use object oriented methods and inheritance to allow different objects to behave in different ways even when called with the same method name. Some languages use a very different approach, such as Julia, which uses [multiple dispatch generic functions](https://docs.julialang.org/en/v1/manual/methods/). Python provides [single dispatch generic functions](https://www.python.org/dev/peps/pep-0443/) as part of the standard library. `fastcore` provides multiple dispatch, with the `typedispatch` decorator (which is actually an instance of `DispatchReg`):
297
297
298
-
```python
298
+
```
299
299
@typedispatch
300
300
def _f(x:numbers.Integral, y): return x+1
301
301
@typedispatch
@@ -324,7 +324,7 @@ This approach to dispatch is particularly useful for adding implementations of f
324
324
325
325
`Transform` looks for three special methods, <code>encodes</code>, <code>decodes</code>, and <code>setups</code>, which provide the implementation for [`__call__`](https://www.python-course.eu/python3_magic_methods.php), `decode`, and `setup` respectively. For instance:
326
326
327
-
```python
327
+
```
328
328
class A(Transform):
329
329
def encodes(self, x): return x+1
330
330
@@ -340,7 +340,7 @@ A()(1)
340
340
341
341
For simple transforms like this, you can also use `Transform` as a decorator:
"`Config` searches parent directories for a config file, and provides direct access to the 'DEFAULT' section. Keys ending in `_path` are converted to paths in the config file's directory."
1905
+
"`Config` and provides direct access to the 'DEFAULT' section of a `ConfigParser` ini file."
0 commit comments