Comparing if datetime.datetime exists or None - python

I'm running a small app on Google App Engine with Python.
In the model I have a property of type DateTimeProperty, which is datetime.datetime. When it's created there is no value (i.e. "None").
I want compare if that datetime.datetime is None, but I can't.
if object.updated_date is None or object.updated_date >= past:
object.updated_date = now
Both updated_date and past is datetime.datetime.
I get the following error.
TypeError: can't compare datetime.datetime to NoneType
What is the correct way to do this?

Given that the previous discussion seems to have established that either of the variables could be None, one approach would be (assuming you want to set object.updated_date when either of the variables is None):
if None in (past, object.updated_date) or object.updated_date >= past:
object.updated_date = now
point being that the check None in (past, object.updated_date) may be handier than the semantically equivalent alternative (past is None or object.update_date is None) (arguably an epsilon more readable thanks to its better compactness, but it is, of course, an arguable matter of style).
As an aside, and a less-arguable matter of style;-), I strongly recommend against using built-ins' names as names for your own variables (and functions, etc) -- object is such a built-in name which in this context is clearly being used for your own purposes. Using obj instead is more concise, still readable (arguably more so;-), and has no downside. You're unlikely to be "bitten" in any given case by the iffy practice of "shadowing" built-ins' names with your own, but eventually it will happen (as you happen to need the normal meaning of the shadowed name during some later ordinary maintenance operation) and you may be in for a confusing debugging situation then; meanwhile, you risk confusing other readers / maintainers... and are getting absolutely no advantage in return for these disadvantages.
I realize that many of Python's built-ins' names are an "attractive nuisance" in this sense... file, object, list, dict, set, min, max... all apparently attractive name for "a file", "an object", "a list`, etc. But, it's worthwhile to learn to resist this particular temptation!-)

Perhaps you mean:
if object.updated_date and object.updated_date >= past:
If it's truthy (which implies not null), we check that it's also >= past. This uses short-circuit evaluation, which means the second condition isn't checked if the first is falsy.

You want and, not or.
You may also want to use is None.
EDIT:
Since you've determined that object.updated_date isn't None, this only other possibility is that past is None.

Related

Is this the proper way to test if an enum is a specific value? [duplicate]

PEP 8 Programming Recommendations says:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
According to the docs, enum members are singletons. Does that mean they should also be compared by identity?
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# like this?
if color is Color.RED:
...
# or like this
if color == Color.RED:
...
When using equality operators, I haven't noticed any issues with this to warrant such strong wording as PEP 8. What's the drawback of using equality, if any? Doesn't it just fall back to an identity-based comparison anyway? Is this just a micro-optimisation?
From https://docs.python.org/3/library/enum.html#module-enum:
Within an enumeration, the members can be compared by identity
In particular, from https://docs.python.org/3/howto/enum.html#comparisons :
Enumeration members are compared by identity
First, we can definitely rule out x.value is y.value, because those aren't singletons, those are perfectly ordinary values that you've stored in attributes.
But what about x is y?
First, I believe that, by "singletons like None", PEP 8 is specifically referring to the small, fixed set of built-in singletons that are like None in some important way. What important way? Why do you want to compare None with is?
Readability: if foo is None: reads like what it means. On the rare occasions when you want to distinguish True from other truthy values, if spam is True: reads better than if spam == True:, as well as making it more obvious that this isn't just a frivolous == True used by someone improperly following a C++ coding standard in Python. That might apply in foo is Potato.spud, but not so much in x is y.
Use as a sentinel: None is used to mean "value missing" or "search failed" or similar cases. It shouldn't be used in cases where None itself can be a value, of course. And if someone creates a class whose instances compare equal to None, it's possible to run into that problem without realizing it. is None protects against that. This is even more of a problem with True and False (again, on those rare occasions when you want to distinguish them), since 1 == True and 0 == False. This reason doesn't seem to apply here—if 1 == Potato.spud, that's only because you intentionally chose to use an IntEnum instead of an Enum, in which case that's exactly what you want…
(Quasi-)keyword status: None and friends have gradually migrated from perfectly normal builtin to keyword over the years. Not only is the default value of the symbol None always going to be the singleton, the only possible value is that singleton. This means that an optimizer, static linter, etc. can make an assumption about what None means in your code, in a way that it can't for anything defined at runtime. Again, this reason doesn't seem to apply.
Performance: This really is not a consideration at all. It might be faster, on some implementations, to compare with is than with ==, but this is incredibly unlikely to ever make a difference in real code (or, if it does, that real code probably needs a higher-level optimization, like turning a list into a set…).
So, what's the conclusion?
Well, it's hard to get away from an opinion here, but I think it's reasonable to say that:
if devo is Potato.spud: is reasonable if it makes things more readable, but as long as you're consistent within a code base, I don't think anyone will complain either way.
if x is y:, even when they're both known to be Potato objects, is not reasonable.
if x.value is Potato.spud.value is not reasonable.
PEP 8 says:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
I disagree with abarnert: the reason for this isn't because these are built-in or special in any way. It's because in these cases you care about having the object, not something that looks like it.
When using is None, for example, you care about whether it's the None that you put there, not a different None that had been passed in. This might be difficult in practice (there is only one None, after all) but it does sometimes matter.
Take, for example:
no_argument = object()
def foo(x=no_argument):
if x OP no_argument:
...
...
If OP is is, this is perfectly idiomatic code. If it's ==, it's not.
For the same reason, you should make the decision as so:
If you want equality to duck type, such as with IntEnum or an Enum that you might want to subclass and overwrite (such as when you have complex enum types with methods and other extras) it makes sense to use ==.
When you are using enums as dumb sentinels, use is.

Use of a temporary variable vs repeatedly read same key/value from a dictionary

Background: I need to read the same key/value from a dictionary (exactly) twice.
Question: There are two ways, as shown below,
Method 1. Read it with the same key twice, e.g.,
sample_map = {'A':1,}
...
if sample_map.get('A', None) is not None:
print("A's value in map is {}".format(sample_map.get('A')))
Method 2. Read it once and store it in a local variable, e.g,
sample_map = {'A':1,}
...
ret_val = sample.get('A', None)
if ret_val is not None:
print("A's value in map is {}".format(ret_val))
Which way is better? What are their Pros and Cons?
Note that I am aware that print() can naturally handle ret_val of None. This is a hypothetical example and I just use it for illustration purposes.
Under these conditions, I wouldn't use either. What you're really interested in is whether A is a valid key, and the KeyError (or lack thereof) raised by __getitem__ will tell you if it is or not.
try:
print("A's value in map is {}".format(sample['A'])
except KeyError:
pass
Or course, some would say there is too much code in the try block, in which case method 2 would be preferable.
try:
ret_val = sample['A']
except KeyError:
pass
else:
print("A's value in map is {}".format(ret_val))
or the code you already have:
ret_val = sample.get('A') # None is the default value for the second argument
if ret_val is not None:
print("A's value in map is {}".format(ret_val))
There isn't any effective difference between the options you posted.
Python: List vs Dict for look up table
Lookups in a dict are about o(1). Same goes for a variable you have stored.
Efficiency is about the same. In this case, I would skip defining the extra variable, since not much else is going on.
But in a case like below, where there's a lot of dict lookups going on, I have plans to refactor the code to make things more intelligible, as all of the lookups clutter or obfuscate the logic:
# At this point, assuming that these are floats is OK, since no thresholds had text values
if vname in paramRanges:
"""
Making sure the variable is one that we have a threshold for
"""
# We might care about it
# Don't check the equal case, because that won't matter
if float(tblChanges[vname][0]) < float(tblChanges[vname][1]):
# Check lower tolerance
# Distinction is important because tolerances are not always the same +/-
if abs(float(tblChanges[vname][0]) - float(tblChanges[vname][1])) >= float(
paramRanges[vname][2]):
# Difference from default is greater than tolerance
# vname : current value, default value, negative tolerance, tolerance units, change date
alerts[vname] = (
float(tblChanges[vname][0]), float(tblChanges[vname][1]), float(paramRanges[vname][2]),
paramRanges[vname][0], tblChanges[vname][2]
)
if abs(float(tblChanges[vname][0]) - float(tblChanges[vname][1])) >= float(
paramRanges[vname][1]):
alerts[vname] = (
float(tblChanges[vname][0]), float(tblChanges[vname][1]), float(paramRanges[vname][1]),
paramRanges[vname][0], tblChanges[vname][2]
)
In most cases—if you can't just rewrite your code to use EAFP as chepner suggests, which you probably can for this example—you want to avoid repeated method calls.
The only real benefit of repeating the get is saving an assignment statement.
If your code isn't crammed in the middle of a complex expression, that just means saving one line of vertical space—which isn't nothing, but isn't a huge deal.
If your code is crammed in the middle of a complex expression, pulling the get out may force you to rewrite things a bit. You may have to, e.g., turn a lambda into a def, or turn a while loop with a simple condition into a while True: with an if …: break. Usually that's a sign that you, e.g., really wanted a def in the first place, but "usually" isn't "always". So, this is where you might want to violate the rule of thumb—but see the section at the bottom first.
On the other side…
For dict.get, the performance cost of repeating the method is pretty tiny, and unlikely to impact your code. But what if you change the code to take an arbitrary mapping object from the caller, and someone passes you, say, a proxy that does a get by making a database query or an RPC to a remote server?
For single-threaded code, calling dict.get with the same arguments twice in a row without doing anything in between is correct. But what if you're taking a dict passed by the caller, and the caller has a background thread also modifying the same dict? Then your code is only correct if you put a Lock or other synchronization around the two accesses.
Or, what if your expression was something that might mutate some state, or do something dangerous?
Even if nothing like this is ever going to be an issue in your code, unless that fact is blindingly obvious to anyone reading your code, they're still going to have to think about the possibility of performance costs and ToCToU races and so on.
And, of course, it makes at least two of your lines longer. Assuming you're trying to write readable code that sticks to 72 or 79 or 99 columns, horizontal space is a scarce resource, while vertical space is much less of a big deal. I think your second version is easier to scan than your first, even without all of these other considerations, but imagine making the expression, say, 20 characters longer.
In the rare cases where pulling the repeated value out of an expression would be a problem, you still often want to assign it to a temporary.
Unfortunately, up to Python 3.7, you usually can't. It's either clumsy (e.g., requiring an extra nested comprehension or lambda just to give you an opportunity to bind a variable) or impossible.
But in Python 3.8, PEP 572 assignment expressions handle this case.
if (sample := sample_map.get('A', None)) is not None:
print("A's value in map is {}".format(sample))
I don't think this is a great use of an assignment expression (see the PEP for some better examples), especially since I'd probably write this the way chepner suggested… but it does show how to get the best of both worlds (assigning a temporary, and being embeddable in an expression) when you really need to.

what does it mean by 'passed by assignment'?

As follow is my understanding of types & parameters passing in java and python:
In java, there are primitive types and non-primitive types. Former are not object, latter are objects.
In python, they are all objects.
In java, arguments are passed by value because:
primitive types are copied and then passed, so they are passed by value for sure. non-primitive types are passed by reference but reference(pointer) is also value, so they are also passed by value.
In python, the only difference is that 'primitive types'(for example, numbers) are not copied, but simply taken as objects.
Based on official doc, arguments are passed by assignment. What does it mean by 'passed by assignment'? Is objects in java work the same way as python? What result in the difference (passed by value in java and passed by argument in python)?
And is there any wrong understanding above?
tl;dr: You're right that Python's semantics are essentially Java's semantics, without any primitive types.
"Passed by assignment" is actually making a different distinction than the one you're asking about.1 The idea is that argument passing to functions (and other callables) works exactly the same way assignment works.
Consider:
def f(x):
pass
a = 3
b = a
f(a)
b = a means that the target b, in this case a name in the global namespace, becomes a reference to whatever value a references.
f(a) means that the target x, in this case a name in the local namespace of the frame built to execute f, becomes a reference to whatever value a references.
The semantics are identical. Whenever a value gets assigned to a target (which isn't always a simple name—e.g., think lst[0] = a or spam.eggs = a), it follows the same set of assignment rules—whether it's an assignment statement, a function call, an as clause, or a loop iteration variable, there's just one set of rules.
But overall, your intuitive idea that Python is like Java but with only reference types is accurate: You always "pass a reference by value".
Arguing over whether that counts as "pass by reference" or "pass by value" is pointless. Trying to come up with a new unambiguous name for it that nobody will argue about is even more pointless. Liskov invented the term "call by object" three decades ago, and if that never caught on, anything someone comes up with today isn't likely to do any better.
You understand the actual semantics, and that's what matters.
And yes, this means there is no copying. In Java, only primitive values are copied, and Python doesn't have primitive values, so nothing is copied.
the only difference is that 'primitive types'(for example, numbers) are not copied, but simply taken as objects
It's much better to see this as "the only difference is that there are no 'primitive types' (not even simple numbers)", just as you said at the start.
It's also worth asking why Python has no primitive types—or why Java does.2
Making everything "boxed" can be very slow. Adding 2 + 3 in Python means dereferencing the 2 and 3 objects, getting the native values out of them, adding them together, and wrapping the result up in a new 5 object (or looking it up in a table because you already have an existing 5 object). That's a lot more work than just adding two ints.3
While a good JIT like Hotspot—or like PyPy for Python—can often automatically do those optimizations, sometimes "often" isn't good enough. That's why Java has native types: to let you manually optimize things in those cases.
Python, instead, relies on third-party libraries like Numpy, which let you pay the boxing costs just once for a whole array, instead of once per element. Which keeps the language simpler, but at the cost of needing Numpy.4
1. As far as I know, "passed by assignment" appears a couple times in the FAQs, but is not actually used in the reference docs or glossary. The reference docs already lean toward intuitive over rigorous, but the FAQ, like the tutorial, goes much further in that direction. So, asking what a term in the FAQ means, beyond the intuitive idea it's trying to get across, may not be a meaningful question in the first place.
2. I'm going to ignore the issue of Java's lack of operator overloading here. There's no reason they couldn't include special language rules for a handful of core classes, even if they didn't let you do the same thing with your own classes—e.g., Go does exactly that for things like range, and people rarely complain.
3. … or even than looping over two arrays of 30-bit digits, which is what Python actually does. The cost of working on unlimited-size "bigints" is tiny compared to the cost of boxing, so Python just always pays that extra, barely-noticeable cost. Python 2 did, like Java, have separate fixed and bigint types, but a couple decades of experience showed that it wasn't getting any performance benefits out of the extra complexity.
4. The implementation of Numpy is of course far from simple. But using it is pretty simple, and a lot more people need to use Numpy than need to write Numpy, so that turns out to be a pretty decent tradeoff.
Similar to passing reference types by value in C#.
Docs: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters#passing-reference-types-by-value
Code demo:
# mutable object
l = [9, 8, 7]
def createNewList(l1: list):
# l1+[0] will create a new list object, the reference address of the local variable l1 is changed without affecting the variable l
l1 = l1+[0]
def changeList(l1: list):
# Add an element to the end of the list, because l1 and l refer to the same object, so l will also change
l1.append(0)
print(l)
createNewList(l)
print(l)
changeList(l)
print(l)
# immutable object
num = 9
def changeValue(val: int):
# int is an immutable type, and changing the val makes the val point to the new object 8,
# it's not change the num value
value = 8
print(num)
changeValue(num)
print(num)

Comparison of objects of distinct types

What's the suggested Python semantics for ordering of objects of distinct types? In other words, what behavior should one implement when a custom-written comparison method (using rich comparisons like e.g. __lt__, but perhaps also when using the ‘poor’ comparison __cmp__ in Python 2) encounters an object of a different type than self?
Should one invent an order, e.g. “all unexpected objects compare as less than my own type”?
Should one throw a TypeError?
Is there some easy way to let the other object have a try, i.e. if one does foo < bar and foo.__lt__ doesn't know about bar's type, can it fall back to bar.__gt__?
Are there any guidelines at all about how to achieve sane ordering of objects of distinct types, preferrably a total order but perhaps less?
Is there any part in the documentation which explains why 3 < "3"?
PEP 207 apparently leaves a lot of freedom of how things can be implemented, but nevertheless I expect there might be some guidelines how things should be implemented to help interoperability.
While writing the question, the “similar questions” list made me aware of this post. It mentions NotImplemented as a return value (not exception) of rich comparisons. Searching for this keyword in the docs turned up relevant parts as well:
Python 2 data model:
NotImplemented – This type has a single value. There is a single object with this value. This object is accessed through the built-in name NotImplemented. Numeric methods and rich comparison methods may return this value if they do not implement the operation for the operands provided. (The interpreter will then try the reflected operation, or some other fallback, depending on the operator.) Its truth value is true.
And later on:
A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.
PEP 207:
If the function cannot compare the particular combination of objects, it should return a new reference to Py_NotImplemented.
This answers points 2. and 3. of my original question, at least for the rich comparison scenario. The docs for __cmp__ don't mention NotImplemented at all, which might be the reason why I missed that at first. So this is one more reason to switch to rich comparisons.
I'm still not sure whether returning that value is to be preferred to inventing an order. I guess a lot depends on what ideas the other object might have. And I fear that for a mix of types to achieve any kind of sane orderings, a lot of cooperation might be needed. But perhaps someone else can shed more light on the other parts of my question.

is there ever a reason to use "is"?

Instead of "=="? I know what "is" is, it is comparing the identity of the variable. But when would you ever want to do that? All it has ever done for me is cause problems. After using it for a while (because I felt it made my code more readable), I am not declaring war on "is".
Does anyone use it for something that "==" wouldn't do? I don't understand why they didn't make 'is' the same thing as '==', like they made 'and' the same as '&&' etc. If someone wanted the pointer, they just have to say "id(x) == id(y)" and we wouldn't have this confusion.
It's one of the "gotcha's" in python that I don't understand, and trip a lot of newbies up. The reason I think it trips people up is that they don't get why it would do an identity comparison. What is the point(er)?
Edit:
Thanks for the great answers. I think what new people should take away is "always use '==' unless you know what you are doing"!
Yes, there is a reason.
When you want to compare object-identity ("same object") and not object-equality ("same value"). In almost all cases == (object-equality) is the correct operator to use. (As pointed out in the comments, the trivial case I skipped entirely is the x is None idiom -- None is the sole inhabitant of NoneType.)
One case for object-identity is an identity-cache/dictionary which is a common pattern in some proxy or "inside-out" situations. In this case I don't want the value for "a similar object" back, I want value for "the same object" back.
Happy coding.
Thinking about pointers in Python is wrong. Values in Python are objects and each value represents itself. That is, x is y is only true when x and y evaluate to the same object. When objects are passed in python this same concept holds -- the object itself is passed. No need to think about references.
Python is Call-by-Sharing/Call-by-Object-Sharing although the term "Call-By-Reference" -- which exists in the "official documentation places" -- is often incorrectly used to describe the behavior (perhaps to "ease" the transition from other languages where the term is also often incorrectly used).
There is a huge difference the two. is tests for object identity and == tests for equality.
Consider this simple example:
print [] == [] # True
print [] is [] # False

Categories

Resources