Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
In a code review challenge, I recently had the below code called unpythonic:
def word_count(string):
wc_dict = {}
word = ""
index = 0
while index < len(string):
if string[index].isalnum():
word = word + string[index]
index += 1
else:
if word:
if word.lower() in wc_dict:
wc_dict[word.lower()] += 1
else:
wc_dict[word.lower()] = 1
word = ""
index += 1
if word:
if word.lower() in wc_dict:
wc_dict[word.lower()] += 1
else:
wc_dict[word.lower()] = 1
return wc_dict
I also submitted different code for a challenge I wrote in Ruby, and had that solution called "Pythonic".
What does code mean to be Pythonic/Unpythonic?
I would say that "pythonic" means "conforming to usual idioms for python in order to write easy to read code". Your example is not pythonic as it could (probably) be written much more easily.
e.g. using regular expressions + collections.Counter turns this into a pretty obvious 2-liner:
words = re.findall(r'\w+', string)
wc_dict = collections.Counter(words)
If you only expect to be splitting on whitespace, that makes it even easier:
wc_dict = collections.Counter(string.split())
95% of the time, if you're working with single characters from a string, there's a better way.
I very much agree with #mgilson's definition of (un-)Pythonic above, but will expand on this case a little more.
I would say that one of the reasons this code was probably described as "un-Pythonic" is because it appears to be a fairly literal translation of C code to do the same thing. I've also seen many cases of Python code that appeared to be based on familiarity with Java or C#, and their respective data structures, standard libraries, and stylistic conventions.
Other than dict, the OP's code doesn't appear to use any of Python's advanced data structures or iteration capabilities.
Even where dict is used, it's in kind of a less-than-fluent way. This code:
if word.lower() in wc_dict:
wc_dict[word.lower()] += 1
else:
wc_dict[word.lower()] = 1
... could be replaced trivially with a more succinct version (this could also be shortened into a one-liner with defaultdict):
wc_dict.setdefault(word.lower(), 0)
wc_dict[word.lower()] += 1
None of this is meant as a criticism of the OP as a thoughtful programmer, by the way: this is a seemingly reasonable and correct algorithm to solve the problem. It just doesn't take advantage of many Python features which experienced users will be familiar with.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have been struggling with a task to check if a password has different attributes without for loop. Such as if it has lower case letters, upper case letters, numbers, symbols and so on. would really appreciate some help on the matter. I am new to recursive functions so I would be more than pleased if someone has an idea for a solution not involving them in python.
My attempt so far:
def strength(password):
if password[1:].isnumeric:
score = 0
if password[1:].isalpha():
score += 3
if password[1:].islower():
score += 2
if password[1:].isupper():
score += 2
if password[1:].isalpha():
score += 3
return score
Sorry that I didn't put this earlier, I'm still a little new to the site. This code only checks whether the entire password is numeric or lowercase or so on to my understanding. How can I extend this to check for other criteria, such as containing symbols?
You can create functions to check on each of those attributes (some of those already exist for Python's str object but it's a good exercise). The any operator will be your friend here:
def contains_upper(string):
uppers = 'ACBDEFGHIJKLMNOPQRSTUVWXYZ'
return any(s in uppers for s in string)
def contains_lower(string):
# etc... you should implement functions to check other attributes
Now create another function to assess if a given string pass all those tests:
def is_valid_password(string):
if not contains_upper(string):
return False
if not contains_lower(string):
return False
# do this for all attributes you want to check
return True
Using regular expressions:
import re
regexp = re.compile(r'[a-z]')
if regexp.search(mystring):
print("lower case found")
Then same with [A-Z] and so on
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Some Info:
While this question is repeated multiple times on StackOverflow and, when googled, brings up many answers; neither of these were fully the answer I was looking for. I have seen answers which use libraries like PyCrypto etc. but none of that helped.
The question:
I am looking for a simple way to encrypt a string in python3 using only the default libraries. I was thinking of, for example, making python replace all the letters in the string with a number or a different letter. Below is what I was thinking of, except it's not actual python code. If someone could make it work in python (and possibly shrink it a little) I would be very grateful.
The Code (Not really):
def encrypt():
for letter in string:
if letter = 'a':
letter.change_to('123')
if letter = 'b':
letter.change_to('133')
if letter = 'c':
letter.change_to('124')
if letter = 'd':
letter.change_to('143')
# And so on... #
NOTE: I would also appreciate if you included a way to decrypt the string if you use a different method to the one above because I am still learning and might not understand how your method works.
-Thank you all in advance :)
EDIT: I was asked to write why I don't want to use any external libraries. It is because I want to encrypt data I send from a client program to a server program. The client will likely run on multiple machines and I do not want to install the required libraries (or make my users do it) on all the machines.
Ok, here's a version of what you want using the chr() and ord() functions, which are related to a topic called ASCII. (A good thing to learn about)
def encrypt(originalString):
encryptedString = ""
for letter in originalString:
encryptedString += str(ord(letter))+"*"
return encryptedString[:-1]
def decrypt(encryptedString):
decryptedString = ""
for codeNumber in encryptedString.split("*"):
decryptedString += chr(int(codeNumber))
return decryptedString
s = "The crow flies at midnight"
t = encrypt(s)
u = decrypt(t)
print(s)
print(t)
print(u)
Output:
The crow flies at midnight
84*104*101*32*99*114*111*119*32*102*108*105*101*115*32*97*116*32*109*105*100*110*105*103*104*116
The crow flies at midnight
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am new to Python, could someone give some pointers as to how this C code can be done in Python:
for(i=0, j=0; j<n; i++, j++){
A[i] = A2[j];
}
I gave this as a example. I am working on a web scraping project where I have to compare each word in a string given by the user to another string and should count proximity of each word and the strings I've to compare are in an array.
You are basically copying an array, equivalent to a python list. You could simply do:
A = list(A2)
In a for loop scenario (which isn't even needed due to the availability of the list call), you'd do:
for ind, val in enumerate(A2):
A[ind] = val
you really have many other options too, A2.copy(), A2[:], a list comprehension and in most recent python versions [*A2]. Python generally makes it very easy to do this.
Python supports iteration over collections/iterables (so range, for example) which are generally discrete. So, you can rewrite that as a while loop:
i = 0
j = 0
while j < n:
A[i] = A2[j]
i += 1
j += 1
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I apologize because I am coming from Perl and I am new to Python.
The following example looks very long to me:
#!/usr/bin/python
import re
r = re.compile('(?i)m(|[ldf])(\d+)')
m = r.match(text)
if m:
print m.group(2)
In Perl for example it is only one line and it's pretty readable.
#!/usr/bin/perl
print $2 if /m(|[ldf])(\d+)/i
How can I rewrite my Python example to be simpler. If possible to be as light as it is with Perl.
I am planning to write plenty tests and if I want to keep my code readable I would like to avoid consuming lines that will not help people to understand my program. I guess that something like this below would be more readable that my first solution:
r = R()
if r.exec('(?i)m(|[ldf])(\d+)', text): print r.group(2)
if r.exec('(?i)k(|[rhe])(\d{2})', text): print r.group(2)
Unfortunately in this case I have to write a class for this.
The Python way values clarity over brevity, so things are generally going to be more verbose than they are in Perl. That said, the re.compile step is optional.
m = re.match('(?i)m(|[ldf])(\d+)', text)
if m:
print m.group(2)
In Python, assignments are not expressions; they can't be used as values. So there's no way to skip the separate assignment statement (m = ...) or combine it with the if . And if you want to refer to the match object later, you do need an explicit assignment - there's no global implicit state analogous to the Perl $n variables that stores the capture groups automatically.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
How should one name a list variable with ending s:
fpss,frame_rates, audios,
or
fps_records = []
frame_rate_records = []
audio_records = []
I don't think adding _records to the end adds anything of value. Avoid adding length to names that don't add clarity or insight for future reviewers, which will certainly include yourself. Adding meaningless verbiage will only serve to make your code harder to read and therefore harder to maintain.
If you think you're going to look at fps later and forget it's a list, use fps_list, which directly tells what type it is to any reader.
Please no-one interpret me as suggesting Hungarian notation. But I do do this when I'm starting out with a list, realize order doesn't matter and I need set-like behavior, and then realize I actually needed a mapping in the first place. Using that sort of convention allows me to implement my new structure completely without breaking the old.
For example, see this Python-style pseudo-code:
Iteration 1
def foo():
data = []
get_data_from_source()...
Iteration 2
def foo():
data_list = []
data_set = set()
get_data_from_source()...
Iteration 3
def foo():
data_set = set()
data_dict = {}
get_data_from_source()...
Iteration 4
def foo():
data = {}
get_data_from_source()...
return data
I agree with #Arone, however if required I would go with adding lst(like lst_records) with list(same we follow in legacy lang like vb) variables so if you would start typing lst immediately IDE would start suggesting all list.