Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import sys
- from copy import copy, deepcopy
- """
- Write a class FileIntegerList that gets at init a single parameter, a disk path to a file with an integer on each line, e.g.
- 4
- 3
- 1532
- 13
- 41
- Considering the file above, an instance of FileIntegerList should behave in the following way:
- When we print an instance of the file, only the first three numbers are shown
- # os.chdir('/home/cristi/.PyCharm2019.1/config/scratches')
- # admin:quajk2Ie@pypi.advance.com
- >>> file_list = FileIntegerList('/path/to/file')
- >>> print(file_list)
- # shows only the first three numbers, if any, when the instance is printed
- FileIntergerList: 4, 3, 1532, ...
- The file is opened and read only when the instance is evaluated
- # the file is not read when the instance is instantiated
- >>> file_list = FileIntergerList('/path/to/file')
- # only now the file opened and read
- >>> numbers = list(file_list)
- >>> print(numbers)
- [4, 1532]
- >>> file_list = FileIntergerList('/path/to/file')
- >>> for integer in file_list:
- print(integer)
- 4
- 3
- 1532
- 13
- 41
- After the file has be read once, when the instance was evaluated, at a second
- evaluation the file is not read anymore
- >>> file_list = FileIntergerList('/path/to/file')
- # the file is opened and read
- >>> for number in file_list:
- print(number)
- # the file is not opened again
- >>> for number in file_list:
- print(number)
- The class has a .filter method takes as a single argument a callable that
- takes as a single argument an integer from the file and returns True if it
- should be kept or False if it should be omitted.
- The method .filter returns an instance of FileIntegerList so the filter
- operations can be chained like in the example below.
- The method .filter does not open the file for reading.
- The file will be opened only when the instance is evaluated.
- >>> file_list = FileIntergerList('/path/to/file')
- >>> file_list = file_list.filter(l
- ambda x: x % 2 == 0).filter(lambda x: x % 3 == 0)
- >>> print(file_list)
- An instance can be evaluated to True or False in an if statement
- # when the file is empty OR when the file does not exist
- >>> file_list = FileIntergerList('/path/to/empty/file')
- >>> if not file_list:
- print('The list is empty')
- The list is empty
- # when the file has items
- >>> file_list = FileIntergerList('/path/to/nonempty/file')
- >>> if file_list:
- print('The list is not empty')
- The list is not empty
- Two instances can be added together to form a new list
- >>> file_list_1 = FileIntergerList('/path/to/file1')
- >>> file_list_2 = FileIntergerList('/path/to/file2')
- # The files /path/to/file1 and /path/to/file2 are not opened when
- # this operations is performed
- >>> file_list = file_list_1 + file_list_2
- # Only now the files /path/to/file1 and /path/to/file2 are opened and read
- >>> numbers = list(file_list)
- I can use sum function on a FileIntegerList instance
- >>> file_list = FileIntegerList('/path/to/file1')
- >>> print(sum(file_list))
- 15321
- I can use the keyword in to test the membership of an element
- >>> file_list = FileIntergerList('/path/to/file')
- >>> print(10 in file_list)
- True
- """
- class FileIntegerList:
- def __init__(self, path=None):
- if path and not os.path.isfile(path):
- print("File path {} does not exist. Exiting...".format(path))
- if not isinstance(path, dict):
- self._paths = {
- path: {'filters': []}
- }
- else:
- self._paths = path
- self._data = []
- self._index = None
- self._current_index = 0
- self._all_data_is_loaded = False
- def __len__(self):
- return len(self._data)
- def load_data(self, end=None, start=0):
- if not self._paths:
- return
- for path in self._paths:
- with open(path, 'r') as file:
- for line_num, line in enumerate(file):
- if line_num + start < self._current_index:
- continue
- if end and len(self._data) > end:
- break
- line_is_ok = True
- for func in self._paths[path]['filters']:
- if not func(int(line)):
- line_is_ok = False
- if line_is_ok:
- self._data.append(int(line))
- self._current_index += 1
- start += line_num
- self._all_data_is_loaded = True
- def paint_data(self, end=None):
- if not end:
- self.load_data()
- return self._data
- temp_end = end
- self.load_data(end=temp_end)
- while len(self._data) < end and not self._all_data_is_loaded:
- temp_end += 1
- self.load_data(end=temp_end)
- return self._data
- def __repr__(self):
- if not self._all_data_is_loaded:
- return str(self)
- return ', '.join([str(row) for row in self.paint_data()])
- def __str__(self):
- filtered_data = self.paint_data(end=4)
- _str = ', '.join([str(row) for row in filtered_data[:3]])
- if len(filtered_data) >= 3:
- _str += ', ...'
- return _str
- def __next__(self):
- try:
- if not self._index:
- self._index = 0
- temp_index = self._index
- self.load_data(end=self._index)
- self._index += 1
- return self._data[temp_index]
- except IndexError:
- self._index = None
- raise StopIteration
- def __iter__(self):
- self.load_data()
- return self.paint_data().__iter__()
- def __bool__(self):
- for path in self._paths:
- if not os.path.isfile(path) or os.path.getsize(path) == 0:
- return False
- return True
- @classmethod
- def _new_instance(cls, paths=None):
- self = cls()
- self._paths = paths
- return self
- def filter(self, func):
- paths = deepcopy(self._paths)
- for path in paths:
- paths[path]['filters'].append(func)
- return FileIntegerList._new_instance(
- paths=paths,
- )
- def __add__(self, other):
- if not isinstance(other, FileIntegerList):
- raise ValueError('omfg Value Error')
- paths = copy(self._paths)
- for key, value in other._paths.items():
- if key in paths:
- paths[key].add(value)
- else:
- paths[key] = value
- return FileIntegerList._new_instance(paths=paths)
- a = 'a'
- a1 = FileIntegerList('first_file_1.txt')
- a2 = a1.filter(lambda x: x % 2 == 0)
- a3 = a2.filter(lambda x: x % 5 == 0)
- b1 = FileIntegerList('first_file_2.txt')
- b2 = b1.filter(lambda x: x % 3 == 0)
- c = (a3+b2)
- print(c)
- print(list(b2))
- print(list(a2))
- a = 'a'
- # for i in c:
- # print(i)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement