I've inherited some Python code that looks like this:
name = 'London'
code = '0.1'
notes = 'Capital of England'
ev = model.City(key=key, code=code, name=name or code, notes=notes)
In the spirit of learning, I'd like to know what's going on with the name or code argument. Is this saying 'Use name if it's not null, otherwise use code'?
And what is the technical term for supplying multiple possible arguments like this, so I can read up on it in the Python docs?
Thanks!
Almost. It says use name if it does not evaluate to false. Things that evaluate to false include, but are not limited to:
False
empty sequences ((), [], "")
empty mappings ({})
0
None
Edit Added the link provided by SilentGhost in his comment to the answer.
In python, the or operator returns the first operand, unless it evaluates to false, in which case it returns the second operand. In effect this will use name, with a default fallback of code if name is not specified.
Fire up a Python console:
>>> name = None
>>> code = 0.1
>>> name or code
0.10000000000000001
In case name evaluates to false the expression will evaluate to code. Otherwise name will be used.
Correct, that idiom take the first value that evaluates to True (generally not None). Use with care since valid values (like zero) may inadvertently be forsaken. A safer approach is something like:
if name is not None:
# use name
or
name if name is not None else code
You've it it roughly correct, but 'null' is not precisely what decides. Basically anything that will evaluate to false (0, false, empty string '') will cause the second string to be displayed instead of the first. 'x or y' in this sense is kind of equivalent to:
if x: x
else: y
Some console play:
x = ''
y = 'roar'
x or y
-'roar'
x = 'arf'
x or y
-'arf'
x = False
x or y
-'roar'
In the spirit of learning, I'd like to
know what's going on with the name or
code argument. Is this saying 'Use
name if it's not null, otherwise use
code'?
yes basically but Null in python can mean more than one thing (empty string , none ..)
like in your case:
>>> name = 'London'
>>> code = 0.1
>>> name or code
'London'
>>> name = ''
>>> code = 0.1
>>> name or code
0.1000....
but it weird thew that a function parameter can be integer sometimes and a string other times.
Hope this can help :=)
Related
im trying to code in python (very new to it) and need to check if an xpath is there then variable = the xpath but if not variable = string.
An example is below
if tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()') = true
$value = tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()')
else
$value = ''
You should really start by doing the whole official tutorial before anything else, as it will anwser your question.
First point : Python objects all have a 'truth' value in a boolean context, which is defined by the object's type and actual value. For builtin types, all empty containers (lists, dicts, sets etc), the empty string, all numerical zeros and the None object are false, everything else is true. For non builtin types you'll have to check the package's documentation.
The builtin type bool will also tell you the boolean value of a given object, so all of the below tests are equivalent:
if myobj:
xxx
if bool(myobj):
xxx
if bool(myobj) == True:
xxx
BUT keep in mind that it doesn't imply that bool(myobj) is the same as myobj - the first one is the boolean value of your object, so the following is NOT equivalent (unless myobj is one of True, 1 or 1.0):
if myobj == True:
xxx
Now wrt/ your actual code snippet: it's not valid Python (bad indentation, invalid identifier $value, invalid use of the assignment operator =, missing : after the if and else statements, wrong capitalization for True...)
Assuming you meant:
# let's make this at least readable:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
if tree.xpath(path) == True:
value = tree.xpath(path)
else:
value = ''
The obvious error is the explicit test against True (tree.xpath() doesn't return a boolean). You either have to explicitely cast the return of tree.xpath() to a boolean (which is quite verbose, totally useless and definitly unpythonic) or just let Python do the right thing by removing the == True part of your test.
As a side note: calling tree.xpath twice in a row with the same argument is a waste of processor cycle (both calls will return the same value), so use a variable instead - it will also make your code much more readable and maintainable. The Pythonic version of your code would look something like:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
found = tree.xpath(path)
value = found if found else ''
or even more simply:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
value = tree.xpath(path) or ''
since the or operator will not yield a boolean value but either the first of it's operand that has a true value or the last operand if none has a true value.
#No need to test == if value is bool. and you not check, you assign value with one =
if anything:
#Then do this
else:
#Do this
I would like to output a user input expression to a string.
The reason is that the input expression is user defined. I want to output the result of the expression, and print the statement which lead to this result.
import sys
import shutil
expression1 = sys.path
expression2 = shutil.which
def get_expression_str(expression):
if callable(expression):
return expression.__module__ +'.'+ expression.__name__
else:
raise TypeError('Could not convert expression to string')
#print(get_expression_str(expression1))
# returns : builtins.TypeError: Could not convert expression to string
#print(get_expression_str(expression2))
# returns : shutil.which
#print(str(expression1))
#results in a list like ['/home/bernard/clones/it-should-work/unit_test', ... ,'/usr/lib/python3/dist-packages']
#print(repr(expression1))
#results in a list like ['/home/bernard/clones/it-should-work/unit_test', ... ,'/usr/lib/python3/dist-packages']
I looked into the Python inspect module but even
inspect.iscode(sys.path)
returns False
For those who wonder why it is the reverse of a string parsed to an expression using functools.partial see parse statement string
Background.
A program should work. Should, but it not always does. Because a program need specific resources, OS, OS version, other packages, files, etc. Every program needs different requirements (resources) to function properly.
Which specific requirement are needed can not be predicted. The system knows best which resources are and are not available. So instead of manually checking all settings and configurations let a help program do this for you.
So the user, or developer of a program, specify his requirements together with statements how to to retrieve this information : expressions. Which could be executed using eval. Could. Like mentioned on StackOverflow eval is evil.
Use of eval is hard to make secure using a blacklist, see : http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
Using multiple tips of SO I use a namedtuple, with a string, to compare with the user input string, and a function.
A white-list is better then a blacklist. Only if the parsed expression string match a "bare_expression" then an expression is returned.
This white-list contains more information how to process f.e. the "unit_of_measurement" . It goes to far to explain what and why, but this is needed. The list of the namedtuples is much more then just a white-list and is defined :
Expr_UOfM = collections.namedtuple('Expr_UOfM', ['bare_expression', 'keylist', 'function', 'unit_of_measurement', 'attrlist'])
The namedtuple which match a (very limited) list:
Exp_list = [Expr_UOfM('sys.path', '' , sys.path, un.STR, []),
Expr_UOfM('shutil.which', '', shutil.which, None, [])]
This list may be very long and the content is crucial for further correct processing. Note the first and third field are very similar. There should be a single point of reference, but for me, this is on this moment not possible. Note the string : 'sys.path' is equal to (a part of) the user input, and the expression : sys.path is part of the namedtuple list. A good separation, limiting possible abuse.
If the string and the expression are not 100% identical weird behavior may occur which is very hard to debug.
So it want using the get_expression_str function check if the first and third field are identical. Just for total robustness of
the program.
I use Python 3.4
You could use inspect.getsource() and wrap your expression in a lambda. Then you can get an expression with this function:
def lambda_to_expr_str(lambda_fn):
"""c.f. https://stackoverflow.com/a/52615415/134077"""
if not lambda_fn.__name__ == "<lambda>":
raise ValueError('Tried to convert non-lambda expression to string')
else:
lambda_str = inspect.getsource(lambda_fn).strip()
expression_start = lambda_str.index(':') + 1
expression_str = lambda_str[expression_start:].strip()
if expression_str.endswith(')') and '(' not in expression_str:
# i.e. l = lambda_to_expr_str(lambda x: x + 1) => x + 1)
expression_str = expression_str[:-1]
return expression_str
Usage:
$ lambda_to_expr_str(lambda: sys.executable)
> 'sys.executable'
OR
$ f = lambda: sys.executable
$ lambda_to_expr_str(f)
> 'sys.executable'
And then eval with
$ eval(lambda_to_expr_str(lambda: sys.executable))
> '/usr/bin/python3.5'
Note that you can take parameters with this approach and pass them with the locals param of eval.
$ l = lambda_to_expr_str(lambda x: x + 1) # now l == 'x + 1'
$ eval(l, None, {'x': 1})
> 2
Here be Dragons. There are many pathological cases with this approach:
$ l, z = lambda_to_expr_str(lambda x: x + 1), 1234
$ l
> 'x + 1), 1234'
This is because inspect.getsource gets the entire line of code the lambda was declared on. Getting source of functions declared with def would avoid this problem, however passing a function body to eval is not possible as there could be side effects, i.e. setting variables, etc... Lambda's can produce side effects as well in Python 2, so even more dragons lie in pre-Python-3 land.
Why not use eval?
>>> exp1 = "sys.path"
>>> exp2 = "[x*x for x in [1,2,3]]"
>>> eval(exp1)
['', 'C:\\Python27\\lib\\site-packages\\setuptools-0.6c11-py2.7.egg', 'C:\\Pytho
n27\\lib\\site-packages\\pip-1.1-py2.7.egg', 'C:\\Python27\\lib\\site-packages\\
django_celery-3.1.1-py2.7.egg', 'C:\\Python27\\lib\\site-packages\\south-0.8.4-p
y2.7.egg', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Pyt
hon27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Py
thon27', 'C:\\Python27\\lib\\site-packages', 'C:\\Python27\\lib\\site-packages\\
PIL']
>>> eval(exp2)
[1, 4, 9]
Assume you have a function, that sometimes returns a value, and sometimes doesn't, because there really is nothing you could return in this case, not even a default value or something. Now you want to do something with the result, but of course only when there is one.
Example:
result = function_call(params)
if result:
print result
Is there a way to write this in a more pythonic way, maybe even in one line?
Like that:
print function_call(params) or #nothing
(Note that I mean it shouldn't print "nothing" or "None". It should actually just not print at all, if the result is None)
No; in Python, name binding is a statement and so cannot be used as an expression within a statement. Since print is also a statement you're going to require 3 lines; in Python 3 you could write:
result = function_call(params)
print(result) if result else None
This isn't quite true for name binding within a comprehension or generator, where name binding is a syntax item that has statement-like semantics:
[print(result) for result in generator_call(params) if result]
As Kos says, you can abuse this to create a one-element comprehension:
[print(result) for result in (function_call(params), ) if result]
Another syntax item that performs name binding and can similarly be abused is the lambda expression:
(lambda result: print(result) if result else None)(function_call(params))
Note that in both these cases the operation on the return value must be an expression and not a statement.
I think the more Pythonic version is actually closer to your original:
result = function_call(params)
if result is not None:
do_something(result)
Checking for is (not) None seems very idiomatic to me - I've used it several times myself and I've also seen it used elsewhere[citation-needed].
From the answers up to now I would do that:
>>> from __future__ import print_function #if Python2.7
>>> def filtered_print(txt):
... txt and print(txt)
...
>>> filtered_print('hello world')
hello world
>>> filtered_print('None')
None
>>> filtered_print(None)
>>>
If someone else has a better solution in mind, I am still open for alternatives, though!
Does Python have something like an empty string variable where you can do:
if myString == string.empty:
Regardless, what's the most elegant way to check for empty string values? I find hard coding "" every time for checking an empty string not as good.
Empty strings are "falsy" (python 2 or python 3 reference), which means they are considered false in a Boolean context, so you can just do this:
if not myString:
This is the preferred way if you know that your variable is a string. If your variable could also be some other type then you should use:
if myString == "":
See the documentation on Truth Value Testing for other values that are false in Boolean contexts.
From PEP 8, in the “Programming Recommendations” section:
For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
So you should use:
if not some_string:
or:
if some_string:
Just to clarify, sequences are evaluated to False or True in a Boolean context if they are empty or not. They are not equal to False or True.
The most elegant way would probably be to simply check if its true or falsy, e.g.:
if not my_string:
However, you may want to strip white space because:
>>> bool("")
False
>>> bool(" ")
True
>>> bool(" ".strip())
False
You should probably be a bit more explicit in this however, unless you know for sure that this string has passed some kind of validation and is a string that can be tested this way.
I would test noneness before stripping. Also, I would use the fact that empty strings are False (or Falsy). This approach is similar to Apache's StringUtils.isBlank or Guava's Strings.isNullOrEmpty
This is what I would use to test if a string is either None OR Empty OR Blank:
def isBlank (myString):
return not (myString and myString.strip())
And, the exact opposite to test if a string is not None NOR Empty NOR Blank:
def isNotBlank (myString):
return bool(myString and myString.strip())
I once wrote something similar to Bartek's answer and javascript inspired:
def is_not_blank(s):
return bool(s and not s.isspace())
Test:
print is_not_blank("") # False
print is_not_blank(" ") # False
print is_not_blank("ok") # True
print is_not_blank(None) # False
The only really solid way of doing this is the following:
if "".__eq__(myString):
All other solutions have possible problems and edge cases where the check can fail.
len(myString) == 0 can fail if myString is an object of a class that inherits from str and overrides the __len__() method.
myString == "" and myString.__eq__("") can fail if myString overrides __eq__() and __ne__().
"" == myString also gets fooled if myString overrides __eq__().
myString is "" and "" is myString are equivalent. They will both fail if myString is not actually a string but a subclass of string (both will return False). Also, since they are identity checks, the only reason why they work is because Python uses String Pooling (also called String Internment) which uses the same instance of a string if it is interned (see here: Why does comparing strings using either '==' or 'is' sometimes produce a different result?). And "" is interned from the start in CPython
The big problem with the identity check is that String Internment is (as far as I could find) that it is not standardised which strings are interned. That means, theoretically "" is not necessary interned and that is implementation dependant.
Also, comparing strings using is in general is a pretty evil trap since it will work correctly sometimes, but not at other times, since string pooling follows pretty strange rules.
Relying on the falsyness of a string may not work if the object overrides __bool__().
The only way of doing this that really cannot be fooled is the one mentioned in the beginning: "".__eq__(myString). Since this explicitly calls the __eq__() method of the empty string it cannot be fooled by overriding any methods in myString and solidly works with subclasses of str.
This is not only theoretical work but might actually be relevant in real usage since I have seen frameworks and libraries subclassing str before and using myString is "" might return a wrong output there.
That said, in most cases all of the mentioned solutions will work correctly. This is post is mostly academic work.
Test empty or blank string (shorter way):
if myString.strip():
print("it's not an empty or blank string")
else:
print("it's an empty or blank string")
If you want to differentiate between empty and null strings, I would suggest using if len(string), otherwise, I'd suggest using simply if string as others have said. The caveat about strings full of whitespace still applies though, so don't forget to strip.
if stringname: gives a false when the string is empty. I guess it can't be simpler than this.
I find hardcoding(sic) "" every time for checking an empty string not as good.
Clean code approach
Doing this: foo == "" is very bad practice. "" is a magical value. You should never check against magical values (more commonly known as magical numbers)
What you should do is compare to a descriptive variable name.
Descriptive variable names
One may think that "empty_string" is a descriptive variable name. It isn't.
Before you go and do empty_string = "" and think you have a great variable name to compare to. This is not what "descriptive variable name" means.
A good descriptive variable name is based on its context.
You have to think about what the empty string is.
Where does it come from.
Why is it there.
Why do you need to check for it.
Simple form field example
You are building a form where a user can enter values. You want to check if the user wrote something or not.
A good variable name may be not_filled_in
This makes the code very readable
if formfields.name == not_filled_in:
raise ValueError("We need your name")
Thorough CSV parsing example
You are parsing CSV files and want the empty string to be parsed as None
(Since CSV is entirely text based, it cannot represent None without using predefined keywords)
A good variable name may be CSV_NONE
This makes the code easy to change and adapt if you have a new CSV file that represents None with another string than ""
if csvfield == CSV_NONE:
csvfield = None
There are no questions about if this piece of code is correct. It is pretty clear that it does what it should do.
Compare this to
if csvfield == EMPTY_STRING:
csvfield = None
The first question here is, Why does the empty string deserve special treatment?
This would tell future coders that an empty string should always be considered as None.
This is because it mixes business logic (What CSV value should be None) with code implementation (What are we actually comparing to)
There needs to be a separation of concern between the two.
How about this? Perhaps it's not "the most elegant", but it seems pretty complete and clear:
if (s is None) or (str(s).strip()==""): // STRING s IS "EMPTY"...
if you want to check if a string is completely empty
if not mystring
which works because empty strings are false
but if a string is only whitespace it will be true so you might want to
if not mystring.strip()
Responding to #1290. Sorry, no way to format blocks in comments. The None value is not an empty string in Python, and neither is (spaces). The answer from Andrew Clark is the correct one: if not myString. The answer from #rouble is application-specific and does not answer the OP's question. You will get in trouble if you adopt a peculiar definition of what is a "blank" string. In particular, the standard behavior is that str(None) produces 'None', a non-blank string.
However if you must treat None and (spaces) as "blank" strings, here is a better way:
class weirdstr(str):
def __new__(cls, content):
return str.__new__(cls, content if content is not None else '')
def __nonzero__(self):
return bool(self.strip())
Examples:
>>> normal = weirdstr('word')
>>> print normal, bool(normal)
word True
>>> spaces = weirdstr(' ')
>>> print spaces, bool(spaces)
False
>>> blank = weirdstr('')
>>> print blank, bool(blank)
False
>>> none = weirdstr(None)
>>> print none, bool(none)
False
>>> if not spaces:
... print 'This is a so-called blank string'
...
This is a so-called blank string
Meets the #rouble requirements while not breaking the expected bool behavior of strings.
I did some experimentation with strings like '', ' ', '\n', etc. I want isNotWhitespace to be True if and only if the variable foo is a string with at least one non-whitespace character. I'm using Python 3.6. Here's what I ended up with:
isWhitespace = str is type(foo) and not foo.strip()
isNotWhitespace = str is type(foo) and not not foo.strip()
Wrap this in a method definition if desired.
a = ''
b = ' '
a.isspace() -> False
b.isspace() -> True
The clearest approach is:
if s == "":
Benefits:
Additional indication to the programmer what the type of s should be.
"" is not "hard-coding" a magic value any more than x == 0 is.
Some values are fundamental and do not need a named constant; e.g. x % 2 to check for even numbers.
Cannot incorrectly indicate that any falsy value (e.g. []) is an empty string.
Consider how one checks if an integer is 0:
if x == 0:
One certainly should not do:
if not x:
Both integers and strings are primitive value types. Why treat them differently?
not str(myString)
This expression is True for strings that are empty. Non-empty strings, None and non-string objects will all produce False, with the caveat that objects may override __str__ to thwart this logic by returning a falsy value.
You may have a look at this Assigning empty value or string in Python
This is about comparing strings that are empty. So instead of testing for emptiness with not, you may test is your string is equal to empty string with "" the empty string...
for those who expect a behaviour like the apache StringUtils.isBlank or Guava Strings.isNullOrEmpty :
if mystring and mystring.strip():
print "not blank string"
else:
print "blank string"
When you are reading file by lines and want to determine, which line is empty, make sure you will use .strip(), because there is new line character in "empty" line:
lines = open("my_file.log", "r").readlines()
for line in lines:
if not line.strip():
continue
# your code for non-empty lines
If you are not totally sure, that your input is really a string, I would recommend to use isinstance(object, classinfo) link in addition, as shown in the example.
If not, lists or a True bool value could also be evaluated as True.
<script type="text/javascript" src="//cdn.datacamp.com/dcl-react.js.gz"></script>
<div data-datacamp-exercise data-lang="python">
<code data-type="sample-code">
def test_string(my_string):
if isinstance(my_string, str) and my_string:
print("It's a me, String! -> " + my_string)
else:
print("Nope. No, String")
def not_fully_test_string(my_string):
if my_string:
print("It's a me, String??? -> " + str(my_string))
else:
print("Nope. No, String")
print("Testing String:")
test_string("")
test_string(True)
test_string(["string1", "string2"])
test_string("My String")
test_string(" ")
print("\nTesting String or not?")
not_fully_test_string("")
not_fully_test_string(True)
not_fully_test_string(["string1", "string2"])
not_fully_test_string("My String")
not_fully_test_string(" ")
</code>
</div>
If you just use
not var1
it is not possible to difference a variable which is boolean False from an empty string '':
var1 = ''
not var1
> True
var1 = False
not var1
> True
However, if you add a simple condition to your script, the difference is made:
var1 = False
not var1 and var1 != ''
> True
var1 = ''
not var1 and var1 != ''
> False
In case this is useful to someone, here is a quick function i built out to replace blank strings with N/A's in lists of lists (python 2).
y = [["1","2",""],["1","4",""]]
def replace_blank_strings_in_lists_of_lists(list_of_lists):
new_list = []
for one_list in list_of_lists:
new_one_list = []
for element in one_list:
if element:
new_one_list.append(element)
else:
new_one_list.append("N/A")
new_list.append(new_one_list)
return new_list
x= replace_blank_strings_in_lists_of_lists(y)
print x
This is useful for posting lists of lists to a mysql database that does not accept blanks for certain fields (fields marked as NN in schema. in my case, this was due to a composite primary key).
Below is an elegant solution for any number of spaces.
def str_empty(s: str) -> bool:
"""Strip white space and count remaining characters."""
return len(s.strip()) < 1
>>> str_empty(' ')
True
As prmatta posted above, but with mistake.
def isNoneOrEmptyOrBlankString (myString):
if myString:
if not myString.strip():
return True
else:
return False
return False
I'm working through a Python 3 book and came across the string function isidentifier(). The text description is "s.isidentifier() : Returns True if s is non empty and is a valid identifier". I tested it in the Python Shell like this:
>>> s = 'test'
>>> s.isidentifier()
True
>>> 'blah'.isidentifier()
True
I would expect the 2nd statement to return false since 'blah' is not held in a variable. Can anyone explain this? Thanks.
Returns True if s is non empty and is a valid identifier.
What they mean is that s could be valid as an identifier. It doesn't imply that it is an identifier that's in use.
Your first example is showing the same thing: 'test' (what isidentifier is actually checking) is not the name of a variable either. I think you meant
>>> 's'.isidentifier()
True
"isidentifier" doesn't say anything about the "variable" the string being tested is referenced by. So
'blah'.isidentifier()
is identical to
s = 'blah'
s.isidentifier()
In Python, it's never (or rarely) about the "variable" (Python doesn't have variables), it's about the object. In this case, strings.
Python doesn't have "variables". It is more helpful to think in terms of objects.
'blah' definitely exists at the time 'blah'.isidentifier() is called (after all it means that "call isidentifier() method of the string object 'blah'").
So if your understanding were correct, isidentifier() method of string objects should always return True, because at the time of the call, the object definitely exists.
What isidentifier() does is to check that the string object can be used as a valid identifier. Try these two lines in your Python session for example:
>>> a = "$"
>>> "$".isidentifier()
Even though "$" is assigned to the name a, the isidentifier() call returns False since $ is not a valid identifier in Python.
isidentifier is a Python function that simply tests whether a string contains only certain characters (underscore, digits, and alphas) and starts with an alpha or an underscore, so the string can be used for a valid Python identifier. Other functions that test for character classes are isalpha, isalnum, isdigit, and others.
ss = (
'varABC123',
'123ABCvar',
'_123ABCvar',
'var_ABC_123',
'var-ABC-123',
'var.ABC.123',
# check your own strings
)
fmt = '%-15s%-10s%-10s%-10s%-10s'
print(fmt % ('', 'isalpha', 'isalnum', 'isdigit', 'isidentifier'))
for s in ss:
print(fmt % (s, s.isalpha(), s.isalnum(), s.isdigit(), s.isidentifier()))
Result:
isalpha isalnum isdigit isidentifier
varABC123 False True False True
123ABCvar False True False False
_123ABCvar False False False True
var_ABC_123 False False False True
var-ABC-123 False False False False
var.ABC.123 False False False False