Домашни > Another brick in the wall > Решения > Решението на Вяра Тодорова

Резултати
8 точки от тестове
0 точки от учител

8 точки общо

8 успешни теста
2 неуспешни теста
Код
Скрий всички коментари

 1class Material:
 2    def __init__(self, mass):
 3        self.mass = mass
 4        self._is_used = False
 5
 6    @property
 7    def volume(self):
 8        return self.mass / self.density
 9
10    def mark_as_used(self):
11        self._is_used = True
12
13    def check_is_used(self):
14        if self._is_used:
15            raise AssertionError("This material is already used")
16
17    def get_is_used(self):
18        return self._is_used
19
20class Concrete(Material):
21    density = 2500
22
23class Brick(Material):
24    density = 2000
25
26class Stone(Material):
27    density = 1600
28
29class Wood(Material):
30    density = 600
31
32class Steel(Material):
33    density = 7700
34
35class Factory:
36    _dynamic_classes = {}
37    _factories = []
38    def __init__(self):
39        self.materials = []
40        Factory._factories.append(self)
41
42    def __call__(self, *args, **kwargs):
43        if args and kwargs:
44            raise ValueError("Cannot mix positional and keyword arguments")
45        if not args and not kwargs:
46            raise ValueError("There must be at least one argument")
47        if args:
48            types_of_given_materials = []
49            for material in args:
50                material.check_is_used()
51                material.mark_as_used()
52                material_type = type(material)
53                if material_type in Factory._dynamic_classes.values():
54                    composite_elements = material_type.__name__.split("_")
55                    types_of_given_materials.extend([globals()[comp] for comp in composite_elements])
56                else:
57                    types_of_given_materials.append(material_type)
58            sorted_types_of_materials = sorted(set(types_of_given_materials), key=lambda cls: cls.__name__)
59            name_of_the_composition = "_".join(cls.__name__ for cls in sorted_types_of_materials)
60            if name_of_the_composition not in Factory._dynamic_classes:
61                composition_density = sum(cls.density for cls in sorted_types_of_materials) / len(sorted_types_of_materials)
62                class CreateMaterial(Material):
63                    density = composition_density
64                CreateMaterial.__name__ = name_of_the_composition
65                Factory._dynamic_classes[name_of_the_composition] = CreateMaterial
66            current_material_class = Factory._dynamic_classes[name_of_the_composition]
67            mass_of_current_material = sum(material.mass for material in args)
68            current_material =  current_material_class(mass_of_current_material)
69            self.materials.append(current_material)
70            return current_material
71        if kwargs:
72            list_of_materials = []
73            for material_name, mass in kwargs.items():
74                material = self._get_class_by_name(material_name)
75                if not material:
76                    raise ValueError("Invalid input")
77                list_of_materials.append(material(mass))
78            self.materials.extend(list_of_materials)
79            return tuple(list_of_materials)
80
81    @staticmethod
82    def _get_class_by_name(name):
83        return globals().get(name) or Factory._dynamic_classes.get(name)
84
85    def can_build(self, volume):
86        full_volume = sum(material.volume for material in self.materials if not material.get_is_used())
87        return full_volume >= volume
88
89    @classmethod
90    def can_build_together(cls, volume):
91        all_materials = []
92        for factory in cls._factories:
93            all_materials.extend(factory.materials)
94
95        full_volume = sum(material.volume for material in all_materials if not material.get_is_used())
96        return full_volume >= volume

.....F.F..
======================================================================
FAIL: test_positional_arguments_multiple_argument_from_initial_set (test.TestFactory.test_positional_arguments_multiple_argument_from_initial_set)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_positional_arguments_multiple_argument_from_initial_set
concrete_wood = self.factory1(concrete, wood)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 50, in __call__
material.check_is_used()
File "/tmp/solution.py", line 15, in check_is_used
raise AssertionError("This material is already used")
AssertionError: This material is already used

======================================================================
FAIL: test_positional_arguments_single_argument (test.TestFactory.test_positional_arguments_single_argument)
Test calling a factory using a sigle positional argument.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 80, in test_positional_arguments_single_argument
self.assertIs(type(concrete2), solution.Concrete)
AssertionError: <class 'solution.Factory.__call__.<locals>.CreateMaterial'> is not <class 'solution.Concrete'>

----------------------------------------------------------------------
Ran 10 tests in 0.010s

FAILED (failures=2)

Дискусия
История
Това решение има само една версия.