packed_source_stream_offsets = bytearray()
for x in source_stream_offset:
packed_source_stream_offsets += varint.encode(x)
Is there a way I can do this on fewer lines or make it more compact? I'm trying to make my code more compact, and I'm wondering if there's a shorter way of doing this.
It's always a bit difficult to answer when there is no reproducible code (e.g. not knowing what source_stream_offset is, or where varint comes from, but I think this should apply in general:
Instead of appending you can use an empty string or byte to join individual parts
You can map over the function rather than using an explicit value
That should yield something like:
bytearray(b''.join(map(varint.encode, source_stream_offset)))
Note: If you're not comfortable with the map syntax, you can also use a list comprehension like:
bytearray(b''.join([varint.encode(x) for x in source_stream_offset]))
Related
For example, if I have lots of lines of coding doing something like:
print('{:=+5d}'.format(my_value))
or perhaps something more involved like:
print('{:04d}-{:04d}|{:03d}'.format(val1, val2, val3))
Is there a good way (and is it good practice) to replace the string format conversion specifier with something so that I:
Reduce the number of times that needs to be typed out
Make it more human readable
Make the format string parametric so it can be changed in one place
Edit for more clarity:
These prints occur throughout the code and aren't just a single list of items in one spot I can loop through. The formats are also used for strings in log messages and other non-print places.
I might want to even specify the string format programmatically
This is running on a legacy python 2 script
Try this:
['{:=+5d}'.format(val) for val in all_vals]
According to python 8.6, you can write this code like this to be more pythonic using something called f-string¹
Code Syntax
print(f'{val1:04d}-{val2:04d}|{val3:03d}')
Say I have a string "abcde", and want to get "deab". How can I get "deab" using string slicing?
I've tried using string[-2:1], but this gives me an empty result ''.
The project I am working on makes splitting this up into [-2:] and [:2] difficult, hence the question. Thanks!
You can simulate wrapping by doubling the string:
(string * 2)[3:7]
This is not necessarily much less efficient than getting two slices the usual way: it only creates one temporary string instead of two, but obviously requires quite a bit more space.
You may want this,
s[-2:] + s[:2]
If I were to take a dictionary, such as
living_beings= {"Reptile":"Snake","mammal":"whale", "Other":"bird"}
and wished to search for individual characters (such as "a") (e.g.
for i in living_beings:
if "a" in living_beings:
print("a is here")
would there be an efficient- runs fastest- method of doing this?
The input is simply searching as outlined above (although my approach didn't work).
My (failed) code goes as follows:
animals=[]
for row in reader: #'reader' is simply what was in the dictionary
animals.append(row) #I tried to turn it into a list to sort it that way
for i in range(1, len(animals)):
r= animals[i]
for i in r:
if i== "a": #My attempt to find "a". This is obviously False as i= one of the strings in
k=i.replace("'","/") #this is my attempt at the further bit, for a bit of context
test= animals.append(k)
print(test)
In case you were wondering,
The next step would be to insert a character- "/"- before that letter (in this case "a"), although this is a slightly different problem and so not linked with my question and is simply there to give a greater understanding of the problem.
EDIT
I have found another error relating to dictionary. If the dictionary features an apostrophe (') the output is affected as it prints that particular word in quotes ("") rather that the normal apostrophes. EXAMPLE: living_beings= {"Reptile":"Snake's","mammal":"whale", "Other":"bird"} and if you use the following code (which I need to):
new= []
for i in living_beings:
r=living_beings[i]
new.append(r)
then the output is "snake's", 'whale', 'bird' (Note the difference between the first and other outputs). So My question is: How to stop the apostrophes affecting output.
My approach would be to use dict comprehension to map over the dictionary and replace every occurence of 'a' by '/a'.
I don't think there are significant performance improvements that can be done from there. You algorithm will be linear with regard to the total number of characters in the keys and items of the dict as you need to traverse the whole dictionary whatever the input.
living_beings= {"Reptile":"Snake","mammal":"whale", "Other":"bird"}
new_dict = {
kind.replace('a', '/a'): animal.replace('a', '/a') for kind, animal in living_beings.items()
}
# new_dict: {"Reptile":"Sn/ake","m/amm/al":"wh/ale", "Other":"bird"}
You could maybe optimize with a more convoluted solution that loops through the dict to mutate it instead of creating a new one, but in general I recommend not trying to do such things in Python. Just write good code, with good practices, and let Python do the optimization under the hood. After all this is what the Zen of Python tells us: Simple is better than complex.
This can be done quite efficiently using a regular expression match, e.g.:
import re
re_containsA = re.compile(r'.*a.*')
for key, word in worddict.items():
if re_containsA.match(word):
print(key)
The re.match object can then be used to find the location of the matched text.
I've recently been practicing using map() in Python 3.5.2, and when I tried to run the module it said the comma separating the function and the iterable was a SyntaxError. Here's the code:
eng_swe = {"merry":"god", "christmas":"jul", "and":"och", "happy":"gott",
"new":"nytt", "year":"år"}
def map_translate(l):
"""Translates English words into Swedish using the dictionary above."""
return list(map(lambda x: eng_swe[x] if x in eng_swe.keys(), l))
I noticed that if I eliminate the conditional statement like this:
return list(map(lambda x: eng_swe[x], l))
it works fine, but it sacrifices the ability to avoid attempting to add items to the list that aren't in the dictionary. Interestingly enough, there also weren't any problems when I tried using a conditional statement with reduce(), as shown here:
from functools import reduce
def reduce_max_in_list(l):
"""Returns maximum integer in list using the 'reduce' function."""
return reduce(lambda x, y: x if x > y else y, l)
Yes, I know I could do the exact same thing more cleanly and easily with a list comprehension, but I consider it worth my time to at least learn how to use map() correctly, even if I end up never using it again.
You're getting the SyntaxError because you're using a conditional expression without supplying the else clause which is mandatory.
The grammar for conditional expressions (i.e if statements in an expression form) always includes an else clause:
conditional_expression ::= or_test ["if" or_test "else" expression]
^^
In your reduce example you do supply it and, as a result, no errors are being raised.
In your first example, you don't specify what should be returned if the condition isn't true. Since python can't yield nothing from an expression, that is a syntax error. e.g:
a if b # SyntaxError.
a if b else c # Ok.
You might argue that it could be useful to implicitly yield None in this case, but I doubt that a proposal of that sort would get any traction within the community... (I wouldn't vote for it ;-)
While the others' explanations of why your code is causing a SyntaxError are completely accurate, the goal of my answer is to aid you in your goal "to at least learn how to use map() correctly."
Your use of map in this context does not make much sense. As you noted in your answer it would be much cleaner if you used a list comprehension:
[eng_swe[x] for x in l if x in eng_swe]
As you can see, this looks awfully similar to your map expression, minus some of the convolution. Generally, this is a sign that you're using map incorrectly. map(lambda... is pretty much a code smell. (Note that I am saying this as an ardent supporter of the use of map in Python. I know many people think it should never be used, but I am not one of those people, as long as it is used properly.)
So, you might be wondering, what is an example of a good time to use map? Well, one use case I can think of off the top of my head is converting a list of strs to ints. For example, if I am reading a table of data stored in a file, I might do:
with open('my_file.txt', 'r') as f:
data = [map(int, line.split(' ')) for line in f]
Which would leave me with a 2d-array of ints, perfect for further manipulation or analysis. What makes this a better use of map than your code is that it uses a built-in function. I am not writing a lambda expressly to be used by map (as this is a sign that you should use a list comprehension).
Getting back to your code, however... if you want to write your code functionally, you should really be using filter, which is just as important to know as map.
map(lambda x: eng_swe[x], filter(lambda x: eng_swe.get(x), l))
Note that I was unable to get rid of the map(lambda... code smell in my version, but at least I broke it down into smaller parts. The filter finds the words that can be translated and the map performs the actual translation. (Still, in this case, a list comprehension is probably better.) I hope that this explanation helps you more than it confuses you in your quest to write Python code functionally.
What is the "pythonic" way to combine a lot of startswith statements?
Here are the details:
I receive various types of messages from a server, which sends them with different first letters in order for receiver to quickly identify and sort them. I wrote a code with a lot of
if message.startswith('A'):
do_A()
elif message.startswith('B'):
do_B()
- like statements. However, I feel there is more pythonic way to write the code without many statements, like maybe to make a list of all possible first letters and have one startswith statement.
Other variants with if message[0]=='A' are even better, since it appears to be faster per this, and speed matters to me.
Use a dictionary mapping first letter to a function:
message_map = {'A': do_A, 'B': do_B}
dispatch = message_map.get(message[:1])
if dispatch is not None:
dispatch()
Functions in Python are first-class objects, so you can store them in a dictionary like this.
Note that I used a slice to get the first character; it'll result in an empty string if message happens to be empty, rather than throw an IndexError exception.