Horrible abuse of __init_subclass__, or elegant hack?
jak
nospam at please.ty
Sun Apr 4 12:18:55 EDT 2021
Il 04/04/2021 11:13, Chris Angelico ha scritto:
> On Sun, Apr 4, 2021 at 6:26 PM jak <nospam at please.ty> wrote:
>>
>> Il 01/04/2021 01:14, Chris Angelico ha scritto:
>>> I think this code makes some sort of argument in the debate about
>>> whether Python has too much flexibility or if it's the best
>>> metaprogramming toolset in the world. I'm not sure which side of the
>>> debate it falls on, though.
>>>
>>> class Building:
>>> resource = None
>>> @classmethod
>>> def __init_subclass__(bldg):
>>> super().__init_subclass__()
>>> print("Building:", bldg.__name__)
>>> def make_recipe(recip):
>>> print(recip.__name__.replace("_", " "), "is made in a",
>>> bldg.__name__.replace("_", " "))
>>> bldg.__init_subclass__ = classmethod(make_recipe)
>>>
>>>
>>> class Extractor(Building): ...
>>> class Refinery(Building): ...
>>>
>>> class Crude(Extractor):
>>> resource = "Oil"
>>> time: 1
>>> Crude: 1
>>>
>>> class Plastic(Refinery):
>>> Crude: 3
>>> time: 6
>>> Residue: 1
>>> Plastic: 2
>>>
>>> class Rubber(Refinery):
>>> Crude: 3
>>> time: 6
>>> Residue: 2
>>> Rubber: 2
>>>
>>> Full code is here if you want context:
>>> https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
>>>
>>> Subclassing Building defines a class that is a building. (The ellipsis
>>> body is a placeholder; I haven't implemented stuff where the buildings
>>> know about their power consumptions and such. Eventually they'll have
>>> other attributes.) But subclassing a building defines a recipe that is
>>> produced in that building. Markers placed before the "time" are
>>> ingredients, those after the "time" are products.
>>>
>>> There are actually a lot of interesting wrinkles to trying to replace
>>> __init_subclass__ on the fly. Things get quite entertaining if you
>>> don't use the decorator, or if you define and decorate the function
>>> outside of the class, or various other combinations.
>>>
>>> On a scale of 1 to "submit this to The Daily WTF immediately", how bad
>>> is this code? :)
>>>
>>> ChrisA
>>>
>>
>> Hi,
>> from https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
>> I get this error:
>>
>> cmd console Win10:
>> $> py -V
>> Python 3.8.6
>>
>> $> py CrisAngelico.py
>> Building: Extractor
>> Building: Refinery
>> Building: Blender
>> Building: Packager
>> Building: Assembler
>> Crude is made in a Extractor
>> Water is made in a Extractor
>> Plastic is made in a Refinery
>> Rubber is made in a Refinery
>> Traceback (most recent call last):
>> File "CrisAngelico.py", line 123, in <module>
>> class Rubber(Refinery):
>> File "CrisAngelico.py", line 72, in make_recipe
>> if net <= alternate["makes"] and costs >= alternate["costs"]:
>> TypeError: '<=' not supported between instances of 'Counter' and 'Counter'
>>
>
> Huh. I forget sometimes which version something was introduced in.
> Apparently the comparison operators on Counters came in with Python
> 3.10. Sorry about that. As an alternative, subtraction is very
> approximately equivalent (if subtracting one counter from another
> yields nothing, then the first one is smaller in total content than
> the second), so it should be possible to adjust it.
>
> ChrisA
>
I modified your code in the following way:
line 65-66:
from:
if (qty <= alternate["per_minute"]
and (costs[Extractor], costs) > (alternate["costs"][Extractor],
alternate["costs"])
to:
if (qty <= alternate["per_minute"]
and (costs[Extractor], set(costs)) >
(alternate["costs"][Extractor], set(alternate["costs"]))
and line 72:
from:
if net <= alternate["makes"] and costs >= alternate["costs"]:
to:
if set(net) <= set(alternate["makes"]) and set(costs) >=
set(alternate["costs"]):
The program runs now. Is the result correct?
Building: Extractor
Building: Refinery
Building: Blender
Building: Packager
Building: Assembler
Crude is made in a Extractor
Water is made in a Extractor
Plastic is made in a Refinery
Rubber is made in a Refinery
Fuel is made in a Refinery
Heavy Oil Residue is made in a Refinery
Polymer Resin is made in a Refinery
Residual Fuel is made in a Refinery
Diluted Fuel is made in a Blender
Canister is made in a Extractor
Package Water is made in a Packager
Diluted Packaged Fuel is made in a Refinery
Unpackage Fuel is made in a Packager
Petroleum Coke is made in a Refinery
Residual Plastic is made in a Refinery
Residual Rubber is made in a Refinery
Recycled Plastic is made in a Refinery
Recycled Rubber is made in a Refinery
Sulfur is made in a Extractor
Coal is made in a Extractor
Compacted is made in a Assembler
Turbofuel is made in a Refinery
Turbo Heavy Fuel is made in a Refinery
Turbo Blend Fuel is made in a Blender
Specify one or more target items
Exit code: 0
(forgive me your trouble)
cheers
More information about the Python-list
mailing list