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
Rephrase the "Private Attributes and Aliases" section (#1351)
It took me a bit to figure out what was meant by the link to the
characteristic issue and why there is no such thing as a private
argument. Incorporate (my understanding of) the meaning inline and also
provide an example of how to work around the _1 syntax error.
Copy file name to clipboardExpand all lines: docs/init.md
+13-8
Original file line number
Diff line number
Diff line change
@@ -66,20 +66,23 @@ We don't think that your business model and your serialization format should be
66
66
## Private Attributes and Aliases
67
67
68
68
One thing people tend to find confusing is the treatment of private attributes that start with an underscore.
69
-
*attrs* follows the doctrine that [there is no such thing as a private argument](https://github.com/hynek/characteristic/issues/6) and strips the underscores from the name when writing the `__init__` method signature:
69
+
Although there is [a convention](https://docs.python.org/3/tutorial/classes.html#tut-private) that members of an object that start with an underscore should be treated as private, consider that a core feature of *attrs* is to automatically create an `__init__` method whose arguments correspond to the members.
70
+
There is no corresponding convention for private arguments: the entire signature of a function is its public interface to be used by callers.
71
+
72
+
However, it is sometimes useful to accept a public argument when an object is constructed, but treat that attribute as private after the object is created, perhaps to maintain some invariant.
73
+
As a convenience for this use case, the default behavior of *attrs* is that if you specify a member that starts with an underscore, it will strip the underscore from the name when it creates the `__init__` method signature:
70
74
71
75
```{doctest}
72
76
>>> import inspect
73
77
>>> from attrs import define
74
78
>>> @define
75
-
... class C:
76
-
... _x: int
77
-
>>> inspect.signature(C.__init__)
78
-
<Signature (self, x: int) -> None>
79
+
... class FileDescriptor:
80
+
... _fd: int
81
+
>>> inspect.signature(FileDescriptor.__init__)
82
+
<Signature (self, fd: int) -> None>
79
83
```
80
84
81
-
There really isn't a right or wrong, it's a matter of taste.
82
-
But it's important to be aware of it because it can lead to surprising syntax errors:
85
+
Even if you're not using this feature, it's important to be aware of it because it can lead to surprising syntax errors:
83
86
84
87
```{doctest}
85
88
>>> @define
@@ -92,6 +95,7 @@ SyntaxError: invalid syntax
92
95
93
96
In this case a valid attribute name `_1` got transformed into an invalid argument name `1`.
94
97
98
+
Whether this feature is useful to you is a matter of taste.
95
99
If your taste differs, you can use the *alias* argument to {func}`attrs.field` to explicitly set the argument name.
96
100
This can be used to override private attribute handling, or make other arbitrary changes to `__init__` argument names.
97
101
@@ -101,8 +105,9 @@ This can be used to override private attribute handling, or make other arbitrary
0 commit comments