mirror of
https://github.com/Brandon-Rozek/website.git
synced 2024-12-01 13:02:27 -05:00
New Posts
This commit is contained in:
parent
a650fc940e
commit
2cc490f3f2
3 changed files with 130 additions and 0 deletions
48
content/blog/copydecorator.md
Normal file
48
content/blog/copydecorator.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
title: "Quick Python: Copy Decorator"
|
||||||
|
date: 2020-04-08T18:49:54-04:00
|
||||||
|
draft: false
|
||||||
|
tags: ["python"]
|
||||||
|
---
|
||||||
|
|
||||||
|
If you want to guarantee that your function doesn't modify any of the references and don't mind paying a price in memory consumption, here is a decorator you can easily add to your functions.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from copy import deepcopy
|
||||||
|
def copy_arguments(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
new_args = deepcopy(args)
|
||||||
|
new_kwargs = deepcopy(kwargs)
|
||||||
|
return func(*new_args, **new_kwargs)
|
||||||
|
return wrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@copy_arguments
|
||||||
|
def modify1(xs):
|
||||||
|
for i, _ in enumerate(xs):
|
||||||
|
xs[i] *= 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Comparison:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def modify2(xs):
|
||||||
|
for i, _ in enumerate(xs):
|
||||||
|
xs[i] *= 2
|
||||||
|
|
||||||
|
a = [1, 2, 3, 4, 5]
|
||||||
|
b = [1, 2, 3, 4, 5]
|
||||||
|
modify1(a)
|
||||||
|
modify2(a)
|
||||||
|
print(a)
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
[1, 2, 3, 4, 5]
|
||||||
|
[2, 4, 6, 8, 10]
|
||||||
|
```
|
||||||
|
|
29
content/blog/pydataclass.md
Normal file
29
content/blog/pydataclass.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
title: "Quick Python: Dataclasses"
|
||||||
|
date: 2020-04-08T18:59:48-04:00
|
||||||
|
draft: false
|
||||||
|
tags: ["python"]
|
||||||
|
---
|
||||||
|
|
||||||
|
Python 3.7 and above have a feature called dataclasses. This allows us to reduce boilerplate code by removing the need to create a whole constructor and providing a sensible `__repr__` function.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Person:
|
||||||
|
name: str
|
||||||
|
age: int
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
```python
|
||||||
|
p = Person("Bob", 30)
|
||||||
|
print(p)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Person(name='Bob', age=20)
|
||||||
|
```
|
||||||
|
|
53
content/blog/pygetset.md
Normal file
53
content/blog/pygetset.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
title: "Quick Python: Getters and Setters"
|
||||||
|
date: 2020-04-08T18:15:21-04:00
|
||||||
|
draft: false
|
||||||
|
tags: ["python"]
|
||||||
|
---
|
||||||
|
|
||||||
|
One of the hidden gems in Python classes are seamless getters and setters. I discovered this through the book [Effective Python by Brett Slatkin](https://effectivepython.com/). Though the example I'll use is different and shorter than the one he uses in his book.
|
||||||
|
|
||||||
|
Let's create a class representing a person. The only information we're going to store is their age and we'll make it optional to provide it.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Person:
|
||||||
|
def __init__(self, age=None):
|
||||||
|
self._age = None
|
||||||
|
@property
|
||||||
|
def age(self):
|
||||||
|
if self._age is None:
|
||||||
|
raise ValueError("age must be set before accessing it.")
|
||||||
|
return self._age
|
||||||
|
@age.setter
|
||||||
|
def age(self, age):
|
||||||
|
if age < 0:
|
||||||
|
raise ValueError("age must be at least zero.")
|
||||||
|
self._age = age
|
||||||
|
```
|
||||||
|
|
||||||
|
The second function in the class decorated by `@property` will be the getter function for the attribute `_age`. The name of the function will be what we expect the user to access it as. The setter is then decorated with `age.setter` where `age` is the name of the attribute. As such the name chosen in the getter function name, setter function name, and decorator must all match.
|
||||||
|
|
||||||
|
Now let's try using it
|
||||||
|
|
||||||
|
```python
|
||||||
|
bobby = Person()
|
||||||
|
bobby.age
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
File "/home/user/test.py", line 7, in age
|
||||||
|
raise ValueError("age must first be set before accessing it")
|
||||||
|
ValueError: age must first be set before accessing it
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
bobby.age = 5
|
||||||
|
bobby.age
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
5
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in a new issue