Asked  7 Months ago    Answers:  5   Viewed   42 times

In Python 2.7, I could get dictionary keys, values, or items as a list:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

Now, in Python >= 3.3, I get something like this:

>>> newdict.keys()
dict_keys([1, 2, 3])

So, I have to do this to get a list:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

I'm wondering, is there a better way to return a list in Python 3?

 Answers

56

Try list(newdict.keys()).

This will convert the dict_keys object to a list.

On the other hand, you should ask yourself whether or not it matters. The Pythonic way to code is to assume duck typing (if it looks like a duck and it quacks like a duck, it's a duck). The dict_keys object will act like a list for most purposes. For instance:

for key in newdict.keys():
  print(key)

Obviously, insertion operators may not work, but that doesn't make much sense for a list of dictionary keys anyway.

Tuesday, June 1, 2021
 
SJain
answered 7 Months ago
60

If you want to use them like that, define the function with the variable names as normal:

def my_function(school, standard, city, name):
    schoolName  = school
    cityName = city
    standardName = standard
    studentName = name

Now you can use ** when you call the function:

data = {'school':'DAV', 'standard': '7', 'name': 'abc', 'city': 'delhi'}

my_function(**data)

and it will work as you want.

P.S. Don't use reserved words such as class.(e.g., use klass instead)

Saturday, June 12, 2021
 
turson
answered 6 Months ago
80

It is already a list

type(my_set)
>>> <type 'list'>

Do you want something like

my_set = set([1,2,3,4])
my_list = list(my_set)
print my_list
>> [1, 2, 3, 4]

EDIT : Output of your last comment

>>> my_list = [1,2,3,4]
>>> my_set = set(my_list)
>>> my_new_list = list(my_set)
>>> print my_new_list
[1, 2, 3, 4]

I'm wondering if you did something like this :

>>> set=set()
>>> set([1,2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object is not callable
Monday, June 21, 2021
 
jsuggs
answered 6 Months ago
51

There are multiple parts of Python's functionality involved here: reading the source code and parsing the string literals, transcoding, and printing. Each has its own conventions.

Short answer:

  • For the purpose of code parsing:
    • str (Py2) -- not applicable, raw bytes from the file are taken
    • unicode (Py2)/str (Py3) -- "source encoding", defaults are ascii (Py2) and utf-8 (Py3)
    • bytes (Py3) -- none, non-ASCII characters are prohibited in the literal
  • For the purpose of transcoding:
    • both (Py2) -- sys.getdefaultencoding() (ascii almost always)
      • there are implicit conversions which often result in a UnicodeDecodeError/UnicodeEncodeError
    • both (Py3) -- none, must specify encoding explicitly when converting
  • For the purpose of I/O:
    • unicode (Py2) -- <file>.encoding if set, otherwise sys.getdefaultencoding()
    • str (Py2) -- not applicable, raw bytes are written
    • str (Py3) -- <file>.encoding, always set and defaults to locale.getpreferredencoding()
    • bytes (Py3) -- none, printing produces its repr() instead

First of all, some terminology clarification so that you understand the rest correctly. Decoding is translation from bytes to characters (Unicode or otherwise), and encoding (as a process) is the reverse. See The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) – Joel on Software to get the distinction.

Now...

Reading the source and parsing string literals

At the start of a source file, you can specify the file's "source encoding" (its exact effect is described later). If not specified, the default is ascii for Python 2 and utf-8 for Python 3. A UTF-8 BOM has the same effect as a utf-8 encoding declaration.

Python 2

Python 2 reads the source as raw bytes. It only uses the "source encoding" to parse a Unicode literal when it sees one. (It's more complicated than that under the hood, but this is the net effect.)

> type t.py
# Encoding: cp1251
s = "абвгд"
us = u"абвгд"
print repr(s), repr(us)
> py -2 t.py
'xe0xe1xe2xe3xe4' u'u0430u0431u0432u0433u0434'

<change encoding declaration in the file to cp866, do not change the contents>
> py -2 t.py
'xe0xe1xe2xe3xe4' u'u0440u0441u0442u0443u0444'

<transcode the file to utf-8, update declaration or replace with BOM>
> py -2 t.py
'xd0xb0xd0xb1xd0xb2xd0xb3xd0xb4' u'u0430u0431u0432u0433u0434'

So, regular strings will contain the exact bytes that are in the file. And Unicode strings will contain the result of decoding the file's bytes with the "source encoding".

If the decoding fails, you will get a SyntaxError. Same if there is a non-ASCII character in the file when there's no encoding specified. Finally, if unicode_literals future is used, any regular string literals (in that file only) are treated as Unicode literals when parsing, with all what that means.

Python 3

Python 3 decodes the entire source file with the "source encoding" into a sequence of Unicode characters. Any parsing is done after that. (In particular, this makes it possible to have Unicode in identifiers.) Since all string literals are now Unicode, no additional transcoding is needed. In byte literals, non-ASCII characters are prohibited (such bytes must be specified with escape sequences), evading the issue altogether.

Transcoding

As per the clarification at the start:

  • str (Py2)/bytes (Py3) -- bytes => can only be decoded (directly, that is; details follow)
  • unicode (Py2)/str (Py3) -- characters => can only be encoded

Python 2

In both cases, if the encoding is not specified, sys.getdefaultencoding() is used. It is ascii (unless you uncomment a code chunk in site.py, or do some other hacks which are a recipe for disaster). So, for the purpose of transcoding, sys.getdefaultencoding() is the "string's default encoding".

Now, here's a caveat:

  • a decode() and encode() -- with the default encoding -- is done implicitly when converting str<->unicode:

    • in string formatting (a third of UnicodeDecodeError/UnicodeEncodeError questions on Stack Overflow are about this)
    • when trying to encode() a str or decode() a unicode (the second third of the Stack Overflow questions)

Python 3

There's no "default encoding" at all: implicit conversion between str and bytes is now prohibited.

  • bytes can only be decoded and str -- encoded, and the encoding argument is mandatory.
  • converting bytes->str (incl. implicitly) produces its repr() instead (which is only useful for debug printing), evading the encoding issue entirely
  • converting str->bytes is prohibited

Printing

This matter is unrelated to a variable's value but related to what you would see on the screen when it's printed -- and whether you will get a UnicodeEncodeError when printing.

Python 2

  • A unicode is encoded with <file>.encoding if set; otherwise, it's implicitly converted to str as per the above. (The final third of the UnicodeEncodeError SO questions fall into here.)
    • For standard streams, the stream's encoding is guessed at startup from various environment-specific sources, and can be overridden with the PYTHONIOENCODING environment variable.
  • str's bytes are sent to the OS stream as-is. What specific glyphs you will see on the screen depends on your terminal's encoding settings (if it's something like UTF-8, you may see nothing at all if you print a byte sequence that is invalid UTF-8).

Python 3

The changes are:

  • Now files opened with text vs. binary mode natively accept str or bytes, correspondingly, and outright refuse to process the wrong type. Text-mode files always have an encoding set, locale.getpreferredencoding(False) being the default.
  • print for text streams still implicitly converts everything to str, which in the case of bytes prints its repr() as per the above, evading the encoding issue altogether
Friday, July 30, 2021
 
Gerardo
answered 5 Months ago
90

You always clear, then append and then insert the same sectionList, that's why it always overwrites the entries - because you told the program it should.

Always remember: In Python assignment never makes a copy!

Simple fix

Just insert a copy:

formatDict[section] = sectionList.copy()    # changed here

Instead of inserting a reference:

formatDict[section] = sectionList  

Complicated fix

There are lots of things going on and you could make it "better" by using functions for subtasks like the grouping, also files should be opened with with so that the file is closed automatically even if an exception occurs and while loops where the end is known should be avoided.

Personally I would use code like this:

def groups(seq, width):
    """Group a sequence (seq) into width-sized blocks. The last block may be shorter."""
    length = len(seq)
    for i in range(0, length, width):   # range supports a step argument!
        yield seq[i:i+width]

# Printing the dictionary could be useful in other places as well -> so
# I also created a function for this.
def print_dict_line_by_line(dct):  
    """Print dictionary where each key-value pair is on one line."""
    for key, value in dct.items():
        print("for key =", key, "value =", value)

def mytask(filename):
    formatDict = {}
    with open(filename) as formatFileHandle:
        # I don't "strip" each line (remove leading and trailing whitespaces/newlines)
        # but if you need that you could also use:
        # for usableLine in (line.strip() for line in formatFileHandle):
        # instead.
        for usableLine in formatFileHandle:
            section = usableLine[:3]
            sectionList = list(groups(usableLine[3:]))
            formatDict[section] = sectionList
    # upon exiting the "with" scope the file is closed automatically!
    print_dict_line_by_line(formatDict)

if __name__ == '__main__':
    mytask('insert your filename here')
Sunday, October 24, 2021
 
Nasenbaer
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share