Skip to content

Commit 9e95062

Browse files
committed
fixes #96
1 parent 35506cf commit 9e95062

File tree

4 files changed

+87
-66
lines changed

4 files changed

+87
-66
lines changed

README.md

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Python is a powerful, dynamic language. Rather than bake everything into the lan
66

77
## Installing
88

9-
To install fastcore run: `conda install -c fastai fastcore` (if you use Anaconda, which we strongly recommend) or `pip install fastcore`. For an [editable install](https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install), clone this repo and run: `pip install -e ".[dev]"`.
9+
To install fastcore run: `conda install fastcore` (if you use Anaconda, which we strongly recommend) or `pip install fastcore`. For an [editable install](https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install), clone this repo and run: `pip install -e ".[dev]"`.
1010

1111
## A tour
1212

@@ -24,7 +24,7 @@ Here's a (somewhat) quick tour of a few higlights, showing examples from each of
2424

2525
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:
2626

27-
```python
27+
```
2828
colab_link('index')
2929
```
3030

@@ -34,7 +34,7 @@ colab_link('index')
3434

3535
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:
3636

37-
```python
37+
```
3838
coll_repr
3939
```
4040

@@ -61,13 +61,13 @@ fastcore's testing module is designed to work well with [nbdev](https://nbdev.fa
6161

6262
Tests look like this:
6363

64-
```python
64+
```
6565
test_eq(coll_repr(range(1000), 5), '(#1000) [0,1,2,3,4...]')
6666
```
6767

6868
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:
6969

70-
```python
70+
```
7171
coll_repr(range(1000), 5)
7272
```
7373

@@ -84,7 +84,7 @@ So every test shown in the docs is also showing you the behavior of the library
8484

8585
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:
8686

87-
```python
87+
```
8888
test_eq([0,1,2,3], np.arange(4))
8989
```
9090

@@ -105,28 +105,28 @@ If you want to check that objects are the same type, rather than the just contai
105105

106106
You can test with any comparison function using `test`, e.g test whether an object is less than:
107107

108-
```python
108+
```
109109
test(2, 3, operator.lt)
110110
```
111111

112112
You can even test that exceptions are raised:
113113

114-
```python
114+
```
115115
def divide_zero(): return 1/0
116116
test_fail(divide_zero)
117117
```
118118

119119
...and test that things are printed to stdout:
120120

121-
```python
121+
```
122122
test_stdout(lambda: print('hi'), 'hi')
123123
```
124124

125125
### Foundations
126126

127127
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):
128128

129-
```python
129+
```
130130
p = Path('images')
131131
p.ls()
132132
```
@@ -140,7 +140,7 @@ p.ls()
140140

141141
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:
142142

143-
```python
143+
```
144144
@patch
145145
def num_items(self:Path): return len(self.ls())
146146
@@ -158,7 +158,7 @@ We also use `**kwargs` frequently. In python `**kwargs` in a parameter like mean
158158

159159
`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:
160160

161-
```python
161+
```
162162
class Author:
163163
def __init__(self, name): self.name = name
164164
@@ -179,7 +179,7 @@ p = ProductPage(Author("Jeremy"), 1.50, 0.50)
179179

180180
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`:
181181

182-
```python
182+
```
183183
class ProductPage:
184184
def __init__(self,author,price,cost): store_attr()
185185
__repr__ = basic_repr('author,price,cost')
@@ -196,7 +196,7 @@ ProductPage("Jeremy", 1.50, 0.50)
196196

197197
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 progressing to customize your class more easily. Here's an example of a class that uses `funcs_kwargs`:
198198

199-
```python
199+
```
200200
@funcs_kwargs
201201
class T:
202202
_methods=['some_method']
@@ -222,7 +222,7 @@ Like most languages, Python allows for very concise syntax for some very common
222222
223223
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`:
224224

225-
```python
225+
```
226226
L(1,2,3)
227227
```
228228

@@ -235,49 +235,49 @@ L(1,2,3)
235235

236236
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:
237237

238-
```python
238+
```
239239
p = L.range(20).shuffle()
240240
p
241241
```
242242

243243

244244

245245

246-
(#20) [17,10,7,18,12,13,5,16,15,19...]
246+
(#20) [18,7,1,11,10,14,3,16,13,15...]
247247

248248

249249

250250
`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:
251251

252-
```python
252+
```
253253
p[2,4,6]
254254
```
255255

256256

257257

258258

259-
(#3) [7,12,5]
259+
(#3) [1,10,3]
260260

261261

262262

263263
It also contains other methods used in `array`, such as `L.argwhere`:
264264

265-
```python
265+
```
266266
p.argwhere(ge(15))
267267
```
268268

269269

270270

271271

272-
(#5) [0,3,7,8,9]
272+
(#5) [0,7,9,16,17]
273273

274274

275275

276276
As you can see from this example, `fastcore` also includes a number of features that make a functional style of programming easier, such as a full range of boolean functions (e.g `ge`, `gt`, etc) which give the same answer as the functions from Python's `operator` module if given two parameters, but return a [curried function](https://en.wikipedia.org/wiki/Currying) if given one parameter.
277277

278278
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`):
279279

280-
```python
280+
```
281281
1 + L(2,3,4)
282282
```
283283

@@ -292,7 +292,7 @@ There's too much functionality to show it all here, so be sure to check the docs
292292

293293
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`):
294294

295-
```python
295+
```
296296
@typedispatch
297297
def _f(x:numbers.Integral, y): return x+1
298298
@typedispatch
@@ -321,7 +321,7 @@ This approach to dispatch is particularly useful for adding implementations of f
321321

322322
`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:
323323

324-
```python
324+
```
325325
class A(Transform):
326326
def encodes(self, x): return x+1
327327
@@ -337,7 +337,7 @@ A()(1)
337337

338338
For simple transforms like this, you can also use `Transform` as a decorator:
339339

340-
```python
340+
```
341341
@Transform
342342
def f(x): return x+1
343343
@@ -353,7 +353,7 @@ f(1)
353353

354354
Transforms can be composed into a `Pipeline`:
355355

356-
```python
356+
```
357357
@Transform
358358
def g(x): return x/2
359359

fastcore/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.0.14"
1+
__version__ = "1.0.15"

0 commit comments

Comments
 (0)