Technical differences in doing nothing vs. pass "" [duplicate] - python

Are these equivalent?
class Empty : pass
and
class Empty:
'''
This class intentionally left blank
'''
The second one seems better for readability and one could put pass at the end but it does not seem necessary.
Is the comment treated as a pass?

Your two codes are almost equivalent, but not quite. pass is just a no-op. The docstring is almost a no-op as well, but it adds a __doc__ attribute to your class object, so there is a small difference.
A version that would be functionally equivalent to using pass would be to use Ellipsis a.k.a. ...:
class Empty: ...
There is nothing special about ... in this case. Any pre-existing object that you don't assign will work just as well. For example, you could replace ... with None, 1, True, etc. The choice of ... is a popular alternative because it is much more aesthetically pleasing. By convention, it means a stub that is to be filled in, while pass usually indicates a deliberate no-op.
Using ... like that will raise a SyntaxError in Python 2. You can use the named Ellipsis object instead, but that is not nearly as pretty.
You may also find this question about the equivalence of pass and return None in functions interesting.

No, they're not equivalent.
Since the implementation of PEP 257, if the first expression in a module, function, or class is a string, that string will be assigned to that module/function/class's __doc__ attribute:
A docstring is a string literal that occurs as the first statement in
a module, function, class, or method definition. Such a docstring
becomes the __doc__ special attribute of that object.
Functionally, the classes are equivalent. However, the difference between having a docstring and not having a docstring can surface when you're creating documentation for your code. Tools like sphinx-autodoc can pick up the docstring and generate documentation for your class, and you'll end up with something like this in your documentation:
class Empty()
This class intentionally left blank
For this reason, it's generally preferable not to use a docstring for this kind of thing. Instead, it would be better to use a comment:
class Empty:
pass # This class intentionally left blank

Related

In python, is there some kind of mapping to return the "False value" of a type?

I am looking for some kind of a mapping function f() that does something similar to this:
f(str) = ''
f(complex) = 0j
f(list) = []
Meaning that it returns an object of type that evaluates to False when cast to bool.
Does such a function exist?
No, there is no such mapping. Not every type of object has a falsy value, and others have more than one. Since the truth value of a class can be customized with the __bool__ method, a class could theoretically have an infinite number of (different) falsy instances.
That said, most builtin types return their falsy value when their constructor is called without arguments:
>>> str()
''
>>> complex()
0j
>>> list()
[]
Nope, and in general, there may be no such value. The Python data model is pretty loose about how the truth-value of a type may be implemented:
object.__bool__(self)
Called to implement truth value testing and the built-in operation
bool(); should return False or True. When this method is not defined,
__len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__()
nor __bool__(), all its instances are considered true.
So consider:
import random
class Wacky:
def __bool__(self):
return bool(random.randint(0,1))
What should f(Wacky) return?
This is actually called an identity element, and in programming is most often seen as part of the definition of a monoid. In python, you can get it for a type using the mzero function in the PyMonad package. Haskell calls it mempty.
Not all types have such a value to begin with. Others may have many such values. The most correct way of doing this would be to create a type-to-value dict, because then you could check if a given type was in the dict at all, and you could chose which value is the correct one if there are multiple options. The drawback is of course that you would have to somehow register every type you were interested in.
Alternatively, you could write a function using some heuristics. If you were very careful about what you passed into the function, it would probably be of some limited use. For example, all the cases you show except complex are containers that generalize with cls().
complex actually works like that too, but I mention it separately because int and float do not. So if your attempt with the empty constructor fails by returning a truthy object or raising a TypeError, you can try cls(0). And so on and so forth...
Update
#juanpa.arrivillaga's answer actually suggests a clever workaround that will work for most classes. You can extend the class and forcibly create an instance that will be falsy but otherwise identical to the original class. You have to do this by extending because dunder methods like __bool__ are only ever looked up on the class, never on an instance. There are also many types where such methods can not be replaced on the instance to begin with. As #Aran-Fey's now-deleted comment points out, you can selectively call object.__new__ or t.__new__, depending on whether you are dealing with a very special case (like int) or not:
def f(t):
class tx(t):
def __bool__(self):
return False
try:
return object.__new__(tx)
except TypeError:
return tx.__new__(tx)
This will only work for 99.9% of classes you ever encounter. It is possible to create a contrived case that raises a TypeError when passed to object.__new__ as int does, and does not allow for a no-arg version of t.__new__, but I doubt you will ever find such a thing in nature. See the gist #Aran-Fey made to demonstrate this.
No such function exists because it's not possible in general. A class may have no falsy value or it may require reversing an arbitrarily complex implementation of __bool__.
What you could do by breaking everything else is to construct a new object of that class and forcibly assign its __bool__ function to one that returns False. Though I suspect that you are looking for an object that would otherwise be a valid member of the class.
In any case, this is a Very Bad Idea in classic style.

Using string formatting within class method docstrings

I have a class with several similar methods, each with long docstrings that are similar but vary with regards to several phrases/words. I'd like to build a docstring template and then apply string formatting to it. Below is a clumsy implementation where the __doc__s are defined after the class methods.
capture_doc = """
%(direc)s normal.
a %(sym)s b."""
class Cls():
def a(self):
pass
def b(self):
pass
a.__doc__ = capture_doc % {'direc' : 'below', 'sym' : '<'}
b.__doc__ = capture_doc % {'direc' : 'above', 'sym' : '>'}
c = Cls()
print(c.a.__doc__)
below normal.
a < b.
Question: is there a Python docs- or PEP-prescribed way to do this? I'd like to keep things basic, I've seen use of an #Appender decorator but think that's a bit fancy for my needs.
You shouldn't do this. You seem to assume your docstring should only serve those who use your code and need help with how it works.
Docstrings are supposed to provide some form of the documentation for the associated object for those reading your code, so this makes your docstring half its worth. I doubt any one would love to go through the trouble of having to format those strings (in their heads or using the interpreter) to figure out what your code does or how it works.
From PEP 257:
What is a Docstring?
A docstring is a string literal that occurs as the first statement
in a module, function, class, or method definition. Such a docstring
becomes the __doc__ special attribute of that object.
[Emphasis mine]
With your implementation, one could pedantically argue you don't have docstrings albeit __doc__ attributes.

Why python docstring is interpreted differently from comment

Let's say, I've got a function like this:
def myFunc():
# useful function to calculate stuff
This will produce an indentation error, unless I add pass:
def myFunc():
# useful function to calculate stuff
pass
However, if I replace a comment with docstring, no pass is necessary:
def myFunc():
"""useful function to calculate stuff"""
This seems like an odd feature as neither of these are used in the program, as far as I know. So, why does it behave like this?
A comment is outright ignored by the interpreter, so omitting a block after an indent is a syntax error. However, a docstring is a real Python object--at its most basic, a literal str. A lone expression is a valid block of code:
'This is a string. It is a valid (though pretty useless) line of Python code.'
In the case of docstrings in particular, there's also some additional functionality going on, such as being used to set the __doc__ attribute.
>>> def myFunc():
... '''MyDocString'''
...
>>> print(myFunc.__doc__)
MyDocString
Note that this also works for classes:
>>> class MyClass(object):
... '''MyClassDocString'''
...
>>> print(MyClass.__doc__)
MyClassDocString
A docstring isn't just a comment. It actually has meaning to the interpreter. In the case with a docstring, you could do myFunc.__doc__ and actually get your docstring back (In the other case with a pass, the result myFunc.__doc__ would be None).
In other words, you are actually adding some code to the function body to modify it's behavior (in some circumstances), so no pass is necessary.

function of a function (property) python

I have a Python class with functions and properties like this:
#property
def xcoords(self):
' Returns numpy array. '
try:
return self.x_coords
except:
self.x_coords = self._read_coords('x')
return self.x_coords
def _read_coords(self, type):
# read lots of stuff from big file
return array
This allows me to do this: data.xcoords, nice and simple.
I want to keep this as it is, however I want to define functions which allow me to do this:
data.xcoords.mm
data.xcoords.in
How do I do it? I also want these function to work for other properties of the class such as data.zcoords.mm.
If you really want xcoords to return a numpy array, then people may not expect the value of xcoords to have mm and in_ methods. You should think about whether mm and in_ are really properties of the arrays themselves, or if they are properties of the class you're defining. In the latter case, I would recommend against subclassing ndarray -- just define them as methods of the containing class.
On the other hand, if these are definitely properties of the thing returned by xcoords, then subclassing ndarray is a reasonable approach. Be sure to get it right by defining __new__ and __array_finalize__ as discussed in the docs.
To decide whether you should subclass ndarray, you might consider whether you can see yourself reusing this class elsewhere in your program. (You don't actually have to use it elsewhere, right now -- you just have to be able to see yourself reusing it at some point.) If you can't, then these are probably properties of the containing class. The line of reasoning here is that -- thinking in terms of functions -- if you have a short function foo and a short function bar, and know you will never call them any other way than foo(bar(x)), you might be better off writing foo_bar instead. The same logic applies to classes.
Finally, as larsmans pointed out, in is a keyword in python, and so isn't available for use in this case (which is why I used in_ above).

Stubbing out functions or classes

Can you explain the concept stubbing out functions or classes taken from this article?
class Loaf:
pass
This class doesn't define any methods or attributes, but syntactically, there needs to be something in the definition, so you use pass. This is a Python reserved word that just means “move along, nothing to see here”. It's a statement that does nothing, and it's a good placeholder when you're stubbing out functions or classes.`
thank you
stubbing out functions or classes
This refers to writing classes or functions but not yet implementing them. For example, maybe I create a class:
class Foo(object):
def bar(self):
pass
def tank(self):
pass
I've stubbed out the functions because I haven't yet implemented them. However, I don't think this is a great plan. Instead, you should do:
class Foo(object):
def bar(self):
raise NotImplementedError
def tank(self):
raise NotImplementedError
That way if you accidentally call the method before it is implemented, you'll get an error then nothing happening.
A 'stub' is a placeholder class or function that doesn't do anything yet, but needs to be there so that the class or function in question is defined. The idea is that you can already use certain aspects of it (such as put it in a collection or pass it as a callback), even though you haven't written the implementation yet.
Stubbing is a useful technique in a number of scenarios, including:
Team development: Often, the lead programmer will provide class skeletons filled with method stubs and a comment describing what the method should do, leaving the actual implementation to other team members.
Iterative development: Stubbing allows for starting out with partial implementations; the code won't be complete yet, but it still compiles. Details are filled in over the course of later iterations.
Demonstrational purposes: If the content of a method or class isn't interesting for the purpose of the demonstration, it is often left out, leaving only stubs.
Note that you can stub functions like this:
def get_name(self) -> str : ...
def get_age(self) -> int : ...
(yes, this is valid python code !)
It can be useful to stub functions that are added dynamically to an object by a third party library and you want have typing hints.
Happens to me... once :-)
Ellipsis ... is preferable to pass for stubbing.
pass means "do nothing", whereas ... means "something should go here" - it's a placeholder for future code. The effect is the same but the meaning is different.
Stubbing is a technique in software development. After you have planned a module or class, for example by drawing it's UML diagram, you begin implementing it.
As you may have to implement a lot of methods and classes, you begin with stubs. This simply means that you only write the definition of a function down and leave the actual code for later. The advantage is that you won't forget methods and you can continue to think about your design while seeing it in code.
The reason for pass is that Python is indentation dependent and expects one or more indented statement after a colon (such as after class or function).
When you have no statements (as in the case of a stubbed out function or class), there still needs to be at least one indented statement, so you can use the special pass statement as a placeholder. You could just as easily put something with no effect like:
class Loaf:
True
and that is also fine (but less clear than using pass in my opinion).

Categories

Resources