This proposal suggests enabling Python developers to use ? or ! as optional suffixes in function and method names, similar to Ruby’s convention. This would provide a quick, visual indicator of functions that either return boolean values (with ?) or may raise exceptions or perform dangerous operations (with !). This optional syntactic enhancement can help developers understand a function’s behavior without always needing to check documentation or rely entirely on IDEs, especially in fast-paced or high-complexity codebases.
Motivation
In languages like Python, knowing whether a function might return None, raise exceptions, or require special handling typically requires checking documentation or relying on IDE hints. While well-documented code and good IDEs help, these systems are not infallible (for example some tools like Github can be hard to look up documentation)
Ruby addresses part of this by allowing ? and ! in method names, helping developers quickly recognize the method’s behavior:
- ?: Indicates the method returns a boolean, such as empty?, valid?, etc.
- !: Indicates the method performs a dangerous or mutative action or may raise an exception, such as save! or delete!.
In Python, adding this optional convention would enhance readability and provide developers with immediate cues about the function’s behavior.
Examples
Boolean-returning Methods (?) In Ruby, a method name like valid? instantly indicates that it returns True or False. In Python, we currently use names like is_valid(). The proposed change would allow:
def valid?():
return some_condition
This immediately signals that the function returns a boolean value, without needing to look up its signature.
Dangerous or Exception-throwing Methods (!) A method that performs dangerous operations, mutates state, or can raise an exception could be named with ! to warn the user:
def save!():
if not self.is_valid():
raise Exception("Invalid state")
# save logic
This would make it clear that save!() might raise an exception or require special care during use, as opposed to a safer save() method.
Benefits
- Readability: Allows developers to infer a function’s behavior (boolean return type, possibility of raising exceptions, or dangerous operations) at a glance.
- Code safety: Functions that mutate state, are unsafe, or throw exceptions can be clearly indicated with !, helping developers identify risks without needing extensive comments or documentation.
- Compatibility with existing Python: This change is entirely optional and would not break existing code. It would be up to individual developers or teams to adopt the convention.
Cross-language Inspiration
Other languages already use naming conventions to make function signatures more self-explanatory:
- Ruby: Methods ending with ? return booleans, and ! signifies mutative/dangerous operations or potential exceptions.
- Swift: Function argument labels like with, for, etc., are required by the syntax, making function signatures more self-explanatory (e.g., func send(to recipient: String)).
- Python: Though Python has keyword arguments that can be descriptive, it doesn’t offer similar syntactic cues in function names themselves.
Here’s an example of how the ? suffix could be applied to an attribute or method that checks for swear words in an object’s username and description, where the description attribute could be None.
Without the ? convention:
def contains_swear_words(user):
if user.description is None:
return has_swear_words(user.username)
return has_swear_words(user.username) or has_swear_words(user.description)
With the ? convention on the description attribute:
def contains_swear_words(user):
if user.description? is None:
return has_swear_words(user.username)
return has_swear_words(user.username) or has_swear_words(user.description?)
Here, the description? attribute signals that the description can be None, making it clearer to anyone reading the code that this value needs special handling. The ? suffix on description? indicates that the attribute might not be present, or could hold a None value, thereby prompting developers to handle it more cautiously.
Conclusion
This optional enhancement would give Python developers more expressive power to signal important aspects of function behavior (returning None, exception raising, mutative operations) directly in the function name. While the change won’t replace good documentation or IDE support, it would provide an additional layer of clarity and code safety.
This change can help avoid certain common errors or misunderstandings, such as forgetting that a function might return None, raise exceptions, or mutate an object. Although it’s a subtle enhancement, it has the potential to improve readability, maintainability, and robustness in Python codebases.