Specifically can I provide append() a Null/None value in Python?
I am trying to add auto complete functionality to a command line application, so am using readline to obtain anything the user may have typed at the raw_input prompt.
I'm getting an issue when I try to tab (with no value entered into the console) and get this message: "append() takes exactly one argument (0 given)"
Here is the code:
tokens = readline.get_line_buffer().split()
if not tokens or readline.get_line_buffer()[-1] == ' ':
tokens.append()
I'm using the example provided here because of the traverse function where the depth of the tree isn't an issue:
https://www.ironalbatross.net/wiki/index.php5?title=Python_Readline_Completions#Complex_problem_.28Regular_Grammar.29
tokens variable is a list, so lists method append really takes exactly one argument.
>>> a = []
>>> a
>>> []
>>> a.append(1)
>>> a
>>> [1]
>>> a.append()
>>> TypeError: append() takes exactly one argument (0 given)
>>> a.append(None)
>>> a
>>> [1, None]
append require exactly one argument
None object can't invoke append function
OK I managed to fix it... wasn't sure what value to provide append() when there was no value returned by readline so did this and it worked:
def complete(self,text,state):
try:
tokens = readline.get_line_buffer().split()
if not tokens or readline.get_line_buffer()[-1] == ' ':
tokens.append(text)
Thanks guys!
Related
def test(lister):
lister.append('why am i being shown in output?')
def pass_the_list():
x = []
test(x)
print(x)
pass_the_list()
Output
['why am i being shown in output?']
Process finished with exit code 0
how to pass string as a reference without return?
The list x is passed as a reference not value, therefore changes made in the function will preserve also when the function finishes.
You can pass a string as a refence, but it doesnt matter, because string, unlike list, is immutable. So any change you do to the string will cause creation of a new object.
test_string = 'Test my immutability'
test_string[0]='B'
>> TypeError: 'str' object does not support item assignment
You can modify string like this though (by putting it into something mutable like list)
test_string = 'Test my immutability'
test_list = [test_string]
def reference_test(test_list):
test_list[0]=test_list[0].replace('Test','Fest')
reference_test(test_list)
print(test_list)
>> ['Rest my immutability']
I am learning how to use the string format method, and I've found something I don't understand. When I do:
>>> s = "My {comp[b]}"
>>> s.format(comp = {'a': 'laptop', 'b': 'desktop'})
'My desktop'
I get the expected results. But when I try to define the dictionary out of the method, and just used the name inside:
>>> comp = {'a': 'laptop', 'b': 'desktop'}
>>> s = "My {comp[b]}"
>>> s.format(comp)
I get KeyError: 'comp'. Why?
In your second example you're not naming the parameter that you're passing to format. Your final line should be:
>>> s.format(comp=comp)
format differentiates the use between positional and named arguments.
By using the name of the variable inside the format string, you are required to give a named argument with that specific name.
In the first you are because you are calling "".format(<name>=<var>) while in the second case your are just giving a positional argument (position 0) that is filled by the comp dictionary.
If you have read the documentation you have noticed that format can use positional arguments in this way: "Hello {0}!".format(<arg0>).
In your second case, instead of giving the required name argument comp you are giving the position argument 0.
This is a part of my homework assignment and im close to the final answer but not quite yet. I need to write a function that writes the odd number between position 1 and 5 in a list.
I make something like that:
-in a file domain I write the condition for odd number:
def oddNumber(x):
"""
this instruction help us to write the odd numbers from the positions specificated
input: x-number
output:-True if the number is odd
-False otherwise
"""
if x % 2==1:
return True
else:
return False
-then the tests:
def testOdd_Number():
testOdd_Number=[0,1,2,3,4,5,6,7,8]
oddNumber(testOdd_Number,0,6)
assert (testOdd_Number==[1,3,5])
oddNumber(testOdd_Number,0,3)
assert (testOdd_Number==[3])
-and in the other file named userinterface I write this:
elif(cmd.startswith("odd from ", "")):
try:
cmd=cmd.replace("odd from ", "")
cmd=cmd.replace("to ", "")
i=int(cmd[:cmd.find(" ")])
j=int(cmd[cmd.find(" "):])
if (i>=len(NumberList) or i>j or j>=len(NumberList) or i<0 or j<0):
print("Invalid value(s).")
else:
for m in range(i-1,j):
if oddNumber(NumberList[m]):
print (NumberList[m])
except:
print("Error!")
-when I run the entire project(I have more requirements but the others one are good), and write odd from [pos] to [pos] it says me
Traceback (most recent call last):
File "C:\Users\Adina\My Documents\LiClipse Workspace\P1\userinterface.py", line 94, in <module>
run()
File "C:\Users\Adina\My Documents\LiClipse Workspace\P1\userinterface.py", line 77, in run
elif(cmd.startswith("odd from ", "")):
TypeError: slice indices must be integers or None or have an __index__ method
I've forgotten to say that I have a also a function main() where I print the requirements.Where am I wrong?
Python's string startswith method, described here:
https://docs.python.org/2/library/stdtypes.html
states that arguments are
some_string.startswith(prefix, beginning, end) #where beginning and end are optional integers
and You have provided prefix and empty string ( cmd.startswith("odd from ", "") )
Some things I noticed:
1) you can shorten your oddNumber function to
def oddNumber(x):
return x%2
2) in your tests, you rebind the functions name testOdd_Number to some list, then pass that around to your oddNumber function. is that the same function described above? Then it won't work, as this function expects a single integer to be passed.
Using the same name to refer to two different things is discouraged.
Actually, I have no idea what your testcode does or should do. Are you passing a list and expect oddNumber to modify it in place?
3) your custom command parser looks... odd, and fragile. Maybe invest in a real parser?
You should decouple command parsing and actual computation.
As brainovergrow pointed out, there is also your error, since .startswith does not accept a string as second argument.
Some general hints:
You can use list(range(9)) instead of hardcoding [0,1,2,3,4,5,6,7,8]
You can use filter to filter the odd numbers of a given list:>>> list(filter(oddNumber, range(9))) yields [1, 3, 5, 7].
You can also use list comprehensions: [x for x in range(9) if x%2] yields the same.
you might find any() and all() useful. Take a look at them.
Your naming scheme is neighter consistent nor pythonic. Read PEP8 for a style guide.
I am trying to make a decrypter that decrypts code from the encrypter I made. I am getting this type error when I run the code though
getcrypt = ''.join(map(Decrypt.get,split_up_into_sixteen_chars(x_str)))
TypeError: split_up_into_sixteen_cjars() takes 0 positional arguments but 1 was given
I'm fairly new to programming and not sure whats causing this.
heres my code
Decrypt = {'1s25FF5ML10IF7aC' : 'A', 1s2afF5ML10I7ac' : 'a'} #I obviously have more than this but I'm trying to make it as simplified as possible
def split_up_into_sixteen_chars():
while len(x_str)>0:
v = x_str[:16]
print(v)
x_str = (input())
getcrypt = ''.join(map(Decrypt.get,split_up_into_sixteen_chars(x_str)))
print(getcrypt)
You have defined a function that takes no parameters:
def split_up_into_sixteen_chars():
yet you are passing it one:
split_up_into_sixteen_chars(x_str)
You need to tell Python that the function takes one parameter here, and name it:
def split_up_into_sixteen_chars(x_str):
The name used does not have to match the name that you pass in for the function call, but it does have to match what you use inside the function. The following function would also work; all I did was rename the parameter:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
print(v)
This works because the parameter some_string becomes a local name, local to the function. It only exists inside of the function, and is gone again once the function completes.
Note that your function creates an infinite loop; the length of some_string will either always be 0, or always be longer than 0. The length does not change in the body of the loop.
The following would work better:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
print(v)
some_string = some_string[16:]
because then we replace some_string with a shorter version of itself each time.
Your next problem is that the function doesn't return anything; Python then takes a default return value of None. Printing is something else entirely, print() writes the data to your console or IDE, but the caller of the function does not get to read that information.
In this case, you really want a generator function, and use yield. Generator functions return information in chunks; you can ask a generator for the next chunk one by one, and that is exactly what map() would do. Change the function to:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
yield v
some_string = some_string[16:]
or even:
def split_up_into_sixteen_chars(some_string):
while some_string:
yield some_string[:16]
some_string = some_string[16:]
because an empty string is 'false-y' when it comes to boolean tests as used by while and if.
As your map(Decrypt.get, ...) stands, if split_up_into_sixteen_chars() yields anything that is not present as a key in Dycrypt, a None is produced (the default value for dict.get() if the key is not there), and ''.join() won't like that. The latter method can only handle strings.
One option would be to return a string default instead:
''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
Now '', the empty string, is returned for chunks that are not present in Decrypt. This makes the whole script work for whatever string input you have:
>>> x_str='Hello world!'
>>> ''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
''
>>> x_str = '1s25FF5ML10IF7aC'
>>> ''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
'A'
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!