【发布时间】:2018-10-19 17:02:12
【问题描述】:
这是我正在做的学校作业......
所以基本上我被要求扫描给定目录并找到其中的所有 .py 文件,并计算给定属性,即文件中定义的类和函数(包括类中的方法),以及总行数和字符数每个文件。并在终端上打印表格中的所有数据。
为了打印表格,我的讲师建议使用一个名为 prettytable 的包,尽管对我来说它一点也不漂亮。
我想使用熊猫。
原因很简单:为每个文件计算它的 4 个属性 --> 这里很自然地想起了一个嵌套字典。 pandas.DataFrame 100% 完美地记录嵌套字典。
扫描和总结是最容易的部分,真正让我陷入困境的是如何使数据容器灵活和可扩展。
内置 dict 无法使用其中的 4 个键值对进行初始化,因此我构建了一个 class CountAttr(MutableMapping) 并使用另一个 class FileCounter 来为每个文件创建并计算每个属性。
但是,pandas.DataFrame 只识别这个类字典对象的第一层。而且我已经阅读了 DataFrame 和 Series 的源文件,仍然无法弄清楚如何解决这个问题。
所以我的问题是,
如何让 pandas.DataFrame/Series 从值是类字典对象的字典中提取数据?
附:我对以下代码、编码风格、实现方式等所有方面的建议持开放态度。非常感谢!
from collections.abc import MutableMapping
from collections import defaultdict
import pandas as pd
import os
class CounterAttr(MutableMapping):
""" Initialize a dictionary with 4 keys whose values are all 0,
keys:value
- 'class': 0
- 'function': 0
- 'line': 0
- 'char': 0
interfaces to get and set these attributes """
def __init__(self):
""" Initially there are 4 attributes in the storage"""
# key: counted attributes | value: counting number
self.__dict__ = {'class': 0, 'function': 0, 'line': 0, 'char': 0}
def __getitem__(self, key):
if key in self.__dict__:
return self.__dict__[key]
else:
raise KeyError
def get(self, key, defaut = None):
if key in self.__dict__:
return self.__dict__[key]
else:
return defaut
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
def __len__(self):
return len(self.__dict__)
def __iter__(self):
return iter(self.__dict__)
def get_all(self):
""" return a copy of the self._storagem, in case the internal data got polluted"""
copy = self.__dict__.copy()
return copy
def to_dict(self):
return self.__dict__
def __repr__(self):
return '{0.__class__.__name__}()'.format(self)
class FileCounter(MutableMapping):
""" Discribe the object the store all the counters for all .py files
Attributes:
-
"""
def __init__(self):
self._storage = dict()
def __setitem__(self, key, value = CounterAttr()):
if key not in self._storage.keys():
self._storage[key] = value
else:
print("Attribute exist!")
def __getitem__(self, key):
if key in self._storage.keys():
return self._storage[key]
else:
self._storage[key] = CounterAttr()
def __delitem__(self, key):
del self._storage[key]
def __len__(self):
return len(self._storage)
def __iter__(self):
return iter(self._storage)
def scan_summerize_pyfile(directory, give_me_dict = False):
""" Scan the passing directory, find all .py file, count the classes, funcs, lines, chars in each file
and print out with a table
"""
file_counter = FileCounter()
if os.path.isdir(directory): # if the given directory is a valid one
os.chdir(directory) # change the CWD
print("\nThe current working directory is {}\n".format(os.getcwd()))
file_lst = os.listdir(directory) # get all files in the CWD
for a_file in file_lst: # traverse the list and find all pyfiles
if a_file.endswith(".py"):
file_counter[a_file]
try:
open_file = open(a_file, 'r')
except FileNotFoundError:
print("File {0} can't be opened!".format(a_file))
else:
with open_file:
for line in open_file:
if line.lstrip().startswith("class"): # count the classes
file_counter[a_file]['class'] += 1
if line.lstrip().startswith("def"): # count the functions
file_counter[a_file]['function'] += 1
file_counter[a_file]['line'] += 1 # count the lines
file_counter[a_file]['char'] += len(line) # count the chars, no whitespace
else:
print("The directory", directory, "is not existed.\nI'm sorry, program ends.")
return file_counter
# Haven't had the pandas codes part yet
【问题讨论】:
-
就最小可重现示例而言,您能否简单地包含从读取文件中获得的示例字典?然后我们可以向您展示如何将它们传递给 DataFrame 构造函数。
-
有点像。
{'filename_0': CountAttr(), 'filename_1': CountAttr()}
标签: python pandas dictionary dataframe