Skip to content
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit ca485d3

Browse files
authored
Updates for PythonTA v1.6.0 (#78)
1 parent ecdd8f2 commit ca485d3

File tree

2 files changed

+114
-119
lines changed

2 files changed

+114
-119
lines changed

index.md

Lines changed: 80 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -87,24 +87,6 @@ print_greeting(name="Arthur")
8787
```
8888

8989

90-
### Used prior global declaration (E0118) {#E0118}
91-
92-
This error occurs when we use a global name prior to the global declaration.
93-
94-
~~~~ {include="E0118_used_prior_global_declaration"}
95-
~~~~
96-
97-
Corrected version:
98-
99-
```python
100-
def timestep() -> None:
101-
"""Increment global time by 1."""
102-
global TIME
103-
print(TIME)
104-
TIME += 1
105-
```
106-
107-
10890
## Type errors
10991

11092
These errors are some of the most common errors we encounter in Python. They generally have to do with using a value of one type where another type is required.
@@ -494,14 +476,6 @@ In the above example, the `pass` statement is "unnecessary" as the program's eff
494476

495477
Good documentation and identifiers are essential for writing software. PyTA helps check to make sure we haven't forgotten to document anything, as well as a basic check on the formatting of our identifiers.
496478

497-
### Missing Docstring (C0111) {#C0111}
498-
499-
This error occurs when a module, function, class or method has no docstring. Special methods like `__init__` do not require a docstring.
500-
501-
~~~~ {include="C0111_missing_docstring"}
502-
~~~~
503-
504-
505479
### Empty Docstring (C0112) {#C0112}
506480

507481
This error occurs when a module, function, class or method has an empty docstring.
@@ -646,14 +620,26 @@ This error occurs when we are trying to access a variable from an imported modul
646620
~~~~
647621

648622

649-
### Import self (W0406) {#W0406}
623+
### Wildcard import (W0401) {#W0401}
650624

651-
A module should not import itself. For example, if we have a module named `W0406_import_self`, it should not import a module with the same name.
625+
We should only import what we need. Wildcard imports (shown below) are generally discouraged, as they add all objects from the imported module into the global namespace. This makes it difficult to tell in which module a particular class, function or constant is defined, and may cause problems, for example, when multiple modules have objects with identical names.
652626

653-
~~~~ {include="W0406_import_self"}
627+
~~~~ {include="W0401_wildcard_import"}
654628
~~~~
655629

656-
This error can occur when the name of our Python file conflicts with the name of a module which we would like to import. For example, if we have a Python file named `math.py`, calling `import math` from within that file (or from within *any* Python file in the same directory) will import *our* `math.py` file, and not the [`math` module] from the standard library.
630+
Rather than importing everything with wildcard `*`, we should specify the names of the objects which we would like to import:
631+
632+
```python
633+
from module_name import SOME_CONSTANT, SomeClass, some_function
634+
```
635+
636+
Or, if we need to import many objects from a particular module, we can import the module itself, and use it as a namespace for the required objects:
637+
638+
```python
639+
import module_name
640+
641+
c = module_name.SomeClass()
642+
```
657643

658644

659645
### Reimported (W0404) {#W0404}
@@ -664,25 +650,34 @@ A module should not be imported more than once.
664650
~~~~
665651

666652

667-
### Wildcard import (W0401) {#W0401}
653+
### Import self (W0406) {#W0406}
668654

669-
We should only import what we need. Wildcard imports (shown below) are generally discouraged, as they add all objects from the imported module into the global namespace. This makes it difficult to tell in which module a particular class, function or constant is defined, and may cause problems, for example, when multiple modules have objects with identical names.
655+
A module should not import itself. For example, if we have a module named `W0406_import_self`, it should not import a module with the same name.
670656

671-
~~~~ {include="W0401_wildcard_import"}
657+
~~~~ {include="W0406_import_self"}
672658
~~~~
673659

674-
Rather than importing everything with wildcard `*`, we should specify the names of the objects which we would like to import:
660+
This error can occur when the name of our Python file conflicts with the name of a module which we would like to import. For example, if we have a Python file named `math.py`, calling `import math` from within that file (or from within *any* Python file in the same directory) will import *our* `math.py` file, and not the [`math` module] from the standard library.
661+
662+
663+
### Multiple imports (C0410) {#C0410}
664+
665+
Different modules should not be imported on a single line.
666+
667+
~~~~ {include="C0410_multiple_imports"}
668+
~~~~
669+
670+
Rather, each module should be imported on a separate line.
675671

676672
```python
677-
from module_name import SOME_CONSTANT, SomeClass, some_function
673+
import sys
674+
import math
678675
```
679676

680-
Or, if we need to import many objects from a particular module, we can import the module itself, and use it as a namespace for the required objects:
677+
Note, however, that we can import multiple functions, classes, or constants on one line, as long as they are from the same module.
681678

682679
```python
683-
import module_name
684-
685-
c = module_name.SomeClass()
680+
from shutil import copy, SameFileError
686681
```
687682

688683

@@ -694,14 +689,6 @@ This error occurs when the [PEP8 import order][PEP8 Imports] is not respected. W
694689
~~~~
695690

696691

697-
### Wrong import position (C0413) {#C0413}
698-
699-
Imports should be placed at the top of the module, above any other code, but below the module docstring.
700-
701-
~~~~ {include="C0413_wrong_import_position"}
702-
~~~~
703-
704-
705692
### Ungrouped imports (C0412) {#C0412}
706693

707694
Imports should be grouped by package.
@@ -717,26 +704,13 @@ from math import floor
717704
```
718705

719706

720-
### Multiple imports (C0410) {#C0410}
707+
### Wrong import position (C0413) {#C0413}
721708

722-
Different modules should not be imported on a single line.
709+
Imports should be placed at the top of the module, above any other code, but below the module docstring.
723710

724-
~~~~ {include="C0410_multiple_imports"}
711+
~~~~ {include="C0413_wrong_import_position"}
725712
~~~~
726713

727-
Rather, each module should be imported on a separate line.
728-
729-
```python
730-
import sys
731-
import math
732-
```
733-
734-
Note, however, that we can import multiple functions, classes, or constants on one line, as long as they are from the same module.
735-
736-
```python
737-
from shutil import copy, SameFileError
738-
```
739-
740714

741715
### Unused import (W0611) {#W0611}
742716

@@ -800,7 +774,7 @@ class Composition(object):
800774

801775
### Abstract method (W0223) {#W0223}
802776

803-
This error occurs when an abstract method (i.e. a method with a `raise NotImplementedError` statement) is not overridden inside a concrete class.
777+
This error occurs when an abstract method (i.e. a method with a `raise NotImplementedError` statement) is not overridden inside a subclass of the abstract class.
804778

805779
~~~~ {include="W0223_abstract_method"}
806780
~~~~
@@ -931,19 +905,19 @@ class SomeNumbers:
931905
```
932906

933907

934-
### Access to member before definition (E0203) {#E0203}
908+
### Method hidden (E0202) {#E0202}
935909

936-
Before trying to use a member of a class, it should have been defined at some point. If we try to use it before assigning to it, an error will occur.
910+
If we accidentally hide a method with an attribute, it can cause other code to attempt to invoke what it believes to be a method, which will fail since it has become an attribute instead. This will cause the program to raise an error.
937911

938-
~~~~ {include="E0203_access_member_before_definition"}
912+
~~~~ {include="E0202_method_hidden"}
939913
~~~~
940914

941915

942-
### Method hidden (E0202) {#E0202}
916+
### Access to member before definition (E0203) {#E0203}
943917

944-
If we accidentally hide a method with an attribute, it can cause other code to attempt to invoke what it believes to be a method, which will fail since it has become an attribute instead. This will cause the program to raise an error.
918+
Before trying to use a member of a class, it should have been defined at some point. If we try to use it before assigning to it, an error will occur.
945919

946-
~~~~ {include="E0202_method_hidden"}
920+
~~~~ {include="E0203_access_member_before_definition"}
947921
~~~~
948922

949923

@@ -959,6 +933,7 @@ Corrected version:
959933
```python
960934
class Animal:
961935
"""A carbon-based life form that eats and moves around."""
936+
_name: str
962937

963938
def __init__(self, name: str) -> None:
964939
self._name = name
@@ -1048,12 +1023,13 @@ Corrected version:
10481023
```python
10491024
class CashRegister:
10501025
"""A cash register for storing money and making change."""
1026+
_current_balance: float
10511027

10521028
def __init__(self, balance: float) -> None:
10531029
self._current_balance = balance
10541030

10551031

1056-
def add_small_coins(nickels: int = 0, dimes: int = 0, quarters: int = 0):
1032+
def add_small_coins(nickels: int = 0, dimes: int = 0, quarters: int = 0) -> float:
10571033
"""Return the dollar value of the small coins."""
10581034
return 0.05 * nickels + 0.10 * dimes + 0.25 * quarters
10591035
```
@@ -1062,9 +1038,9 @@ def add_small_coins(nickels: int = 0, dimes: int = 0, quarters: int = 0):
10621038

10631039
- [W0211](#W0211)
10641040

1065-
### Bad static member (W0211) {#W0211}
1041+
### Bad static method argument (W0211) {#W0211}
10661042

1067-
This error occurs when a static method contains `self` as the first parameter. Static methods are methods that do not operate on instances. If we feel that the logic of a particular function belongs inside a class, we can move that function into the class and add a [`@staticmethod`][Python Documentation: staticmethod] [decorator][Python Documentation: decorator] to signal that the method is a static method which does not take a class instance as the first argument. If such a static method contains `self` as the first parameter, it suggests that we are erroneously expecting a class instance as the first argument to the method.
1043+
This error occurs when a static method has `self` as the first parameter. Static methods are methods that do not operate on instances. If we feel that the logic of a particular function belongs inside a class, we can move that function into the class and add a [`@staticmethod`][Python Documentation: staticmethod] [decorator][Python Documentation: decorator] to signal that the method is a static method which does not take a class instance as the first argument. If such a static method contains `self` as the first parameter, it suggests that we are erroneously expecting a class instance as the first argument to the method.
10681044

10691045
~~~~ {include="W0211_bad_staticmethod_argument"}
10701046
~~~~
@@ -1074,20 +1050,21 @@ Corrected version:
10741050
```python
10751051
class CashRegister:
10761052
"""A cash register for storing money and making change."""
1053+
_current_balance: float
10771054

10781055
def __init__(self, balance: float) -> None:
10791056
self._current_balance = balance
10801057

10811058
@staticmethod
1082-
def add_small_coins(nickels: int = 0, dimes: int = 0, quarters: int = 0):
1059+
def add_small_coins(nickels: int = 0, dimes: int = 0, quarters: int = 0) -> float:
10831060
"""Return the dollar value of the small coins."""
10841061
return 0.05 * nickels + 0.10 * dimes + 0.25 * quarters
10851062
```
10861063

10871064
**See also**:
10881065

10891066
- [R0201](#R0201)
1090-
- [StackOverflow: What is the difference between \@staticmethod and \@classmethod in Python?]
1067+
- [StackOverflow: What is the difference between `@staticmethod` and `@classmethod` in Python?]
10911068

10921069

10931070
## Exceptions
@@ -1207,23 +1184,20 @@ Input / output functions ([`input`], [`open`] and [`print`]) should not be used
12071184
~~~~ {include="E9998_forbidden_io_function"}
12081185
~~~~
12091186

1210-
### Always returning in a loop (E9996) {#E9996}
1211-
1212-
This error occurs when we *always* return something inside a loop body. This means that the loop will execute only once.
1213-
1214-
~~~~ {include="always_returning_example"}
1215-
~~~~
1216-
1217-
### Dynamic Execution (E9991) {#E9991}
1187+
### Only one loop iteration (E9996) {#E9996}
12181188

1219-
Use of builtin functions [`exec`], [`eval`], and [`compile`] is not allowed.
1189+
This error occurs when the loop body only ever executes once.
1190+
This usually occurs when every possible execution path through the body ends in a `return` statement.
12201191

1221-
~~~~ {include="dynamic_execution_example"}
1222-
~~~~
1223-
1224-
**See also**:
1225-
1226-
- [StackOverflow: What's the difference between eval, exec, and compile in Python?]
1192+
```python
1193+
def all_even(nums: List[int]) -> bool:
1194+
"""Return whether nums contains only even numbers."""
1195+
for num in nums:
1196+
if num % 2 == 0:
1197+
return True
1198+
else:
1199+
return False
1200+
```
12271201

12281202
### Unnecessary Indexing (E9994) {E9994}
12291203

@@ -1402,21 +1376,21 @@ def is_int(obj: Union[int, float, str]) -> bool:
14021376

14031377
### Dangerous default value (W0102) {#W0102}
14041378

1405-
This warning occurs when a mutable object, such as a list or dictionary, is provided as a default argument inside a function or a method definition. Default arguments are instantiated only once, at the time when the function or the method is defined (i.e. when the interpreter parses the `def ...` block). If the default argument is modified, it will remain modified in all subsequent calls of the function or method. This leads to a common "gotcha" in Python, where an "empty" list or dictionary, specified as the default argument, starts containing values on calls other than the first call.
1379+
This warning occurs when a mutable object, such as a list or dictionary, is provided as a default argument in a function definition. Default arguments are instantiated only once, at the time when the function is defined (i.e. when the interpreter encounters the `def ...` block). If the default argument is mutated when the function is called, it will remain modified for all subsequent function calls. This leads to a common "gotcha" in Python, where an "empty" list or dictionary, specified as the default argument, starts containing values on calls other than the first call.
14061380

14071381
~~~~ {include="W0102_dangerous_default_value"}
14081382
~~~~
14091383

14101384
Many new users of Python would expect the output of the code above to be:
14111385

1412-
```
1386+
```python
14131387
[0, 1, 2, 3, 4]
14141388
[0, 1, 2, 3, 4]
14151389
```
14161390

14171391
However, the actual output is:
14181392

1419-
```
1393+
```python
14201394
[0, 1, 2, 3, 4]
14211395
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
14221396
```
@@ -1600,35 +1574,35 @@ def func(temp: int) -> bool:
16001574
return temp > 0
16011575
```
16021576

1603-
### Mixed indentation (W0312) {#W0312}
1577+
### Bad indentation (W0311) {#W0311}
16041578

1605-
This error occurs when the code is indented with a mix of tabs and spaces. Please note that [*spaces are the preferred indentation method*][PEP8: Tabs or Spaces?].
1579+
This error occurs when an unexpected number of tabs or spaces is used to indent the code. It is recommended that we use [*four spaces per indentation level*][PEP8: Indentation] throughout our code.
16061580

1607-
~~~~ {include="W0312_mixed_indentation"}
1581+
~~~~ {include="W0311_bad_indentation"}
16081582
~~~~
16091583

16101584
Corrected version:
16111585

16121586
```python
1613-
def hello_world() -> None:
1614-
"""Greet the universe with a friendly 'Hello World!'."""
1615-
print("Hello World!")
1587+
def print_greeting(name: str) -> None:
1588+
"""Print a greeting to the person with the given name."""
1589+
print('Hello {}!'.format(name))
16161590
```
16171591

16181592

1619-
### Bad indentation (W0311) {#W0311}
1593+
### Mixed indentation (W0312) {#W0312}
16201594

1621-
This error occurs when an unexpected number of tabs or spaces is used to indent the code. It is recommended that we use [*four spaces per indentation level*][PEP8: Indentation] throughout our code.
1595+
This error occurs when the code is indented with a mix of tabs and spaces. Please note that [*spaces are the preferred indentation method*][PEP8: Tabs or Spaces?].
16221596

1623-
~~~~ {include="W0311_bad_indentation"}
1597+
~~~~ {include="W0312_mixed_indentation"}
16241598
~~~~
16251599

16261600
Corrected version:
16271601

16281602
```python
1629-
def print_greeting(name: str) -> None:
1630-
"""Print a greeting to the person with the given name."""
1631-
print('Hello {}!'.format(name))
1603+
def hello_world() -> None:
1604+
"""Greet the universe with a friendly 'Hello World!'."""
1605+
print("Hello World!")
16321606
```
16331607

16341608

@@ -1834,9 +1808,6 @@ spam -= 1
18341808
[`input`]: https://docs.python.org/3/library/functions.html#input
18351809
[`open`]: https://docs.python.org/3/library/functions.html#open
18361810
[`print`]: https://docs.python.org/3/library/functions.html#print
1837-
[`exec`]: https://docs.python.org/3/library/functions.html#exec
1838-
[`eval`]: https://docs.python.org/3/library/functions.html#eval
1839-
[`compile`]: https://docs.python.org/3/library/functions.html#compile
18401811

18411812
<!-- Python docs -->
18421813

@@ -1870,8 +1841,7 @@ spam -= 1
18701841
[StackOverflow: About the changing id of an immutable string]: https://stackoverflow.com/questions/24245324/about-the-changing-id-of-an-immutable-string
18711842
[StackOverflow: How To Use The Pass Statement In Python]: https://stackoverflow.com/a/22612774/2063031
18721843
[StackOverflow: What does 'super' do in Python?]: https://stackoverflow.com/q/222877/2063031
1873-
[StackOverflow: What is the difference between \@staticmethod and \@classmethod in Python?]: https://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
1874-
[StackOverflow: What's the difference between eval, exec, and compile in Python?]: https://stackoverflow.com/questions/2220699/whats-the-difference-between-eval-exec-and-compile-in-python
1844+
[StackOverflow: What is the difference between `@staticmethod` and `@classmethod` in Python?]: https://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
18751845
[StackOverflow: When does Python allocate new memory for identical strings?]: https://stackoverflow.com/questions/2123925/when-does-python-allocate-new-memory-for-identical-strings
18761846

18771847
<!-- everything else -->

0 commit comments

Comments
 (0)