Nonetheless, there are two things you can still do to protect your classes' integrity.
### Use the _ naming convention
If you start an attribute/method name by an underscore, it means that it shouldn't be accessed from outside the object.
### Anti-pattern
Don't use setters/getters !
```python
classPerson:
def__init__(self,age):
self._age=age
defget_age(self):
returnself._age
defset_age(self,age):
self._age=age
```
### Good Practice
The attribute should be public:
```python
classPerson:
def__init__(self,age):
self.age=age
```
### To use carefully
If you really need to have a setter (to change another variable, ...), you can (but only if you really need it) use the [@property decorator](https://docs.python.org/3/library/functions.html#property).
You should use [enumerate](https://docs.python.org/3/library/functions.html#enumerate), [zip](https://docs.python.org/3/library/functions.html#zip), when appropriate.
### Anti-pattern
```python
persons=['Jean','Paul','Fred']
foriinrange(len(persons)):
person=persons[i]
print(f'the {i+1}th person in the list is {person}')
```
Or, worse:
```python
persons=['Jean','Paul','Fred']
i=0
forpersoninpersons:
i+=1
print(f'the {i+1}th person in the list is {person}')
```
### Good practice
```python
persons=['Jean','Paul','Fred']
fori,personinenumerate(persons):
print(f'the {i+1}th person in the list is {person}')