#!/usr/bin/env PYTHONHASHSEED=1234 python3# Copyright 2014-2019 Brett Slatkin, Pearson Education Inc.## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.# Reproduce book environmentimport randomrandom.seed(1234)import loggingfrom pprint import pprintfrom sys import stdout as STDOUT# Write all output to a temporary directoryimport atexitimport gcimport ioimport osimport tempfileTEST_DIR = tempfile.TemporaryDirectory()atexit.register(TEST_DIR.cleanup)# Make sure Windows processes exit cleanlyOLD_CWD = os.getcwd()atexit.register(lambda: os.chdir(OLD_CWD))os.chdir(TEST_DIR.name)def close_open_files():everything = gc.get_objects()for obj in everything:if isinstance(obj, io.IOBase):obj.close()atexit.register(close_open_files)# Example 1class Meta(type):def __new__(meta, name, bases, class_dict):global printorig_print = printprint(f'* Running {meta}.__new__ for {name}')print('Bases:', bases)print = pprintprint(class_dict)print = orig_printreturn type.__new__(meta, name, bases, class_dict)class MyClass(metaclass=Meta):stuff = 123def foo(self):passclass MySubclass(MyClass):other = 567def bar(self):pass# Example 2class ValidatePolygon(type):def __new__(meta, name, bases, class_dict):# Only validate subclasses of the Polygon classif bases:if class_dict['sides'] < 3:raise ValueError('Polygons need 3+ sides')return type.__new__(meta, name, bases, class_dict)class Polygon(metaclass=ValidatePolygon):sides = None # Must be specified by subclasses@classmethoddef interior_angles(cls):return (cls.sides - 2) * 180class Triangle(Polygon):sides = 3class Rectangle(Polygon):sides = 4class Nonagon(Polygon):sides = 9assert Triangle.interior_angles() == 180assert Rectangle.interior_angles() == 360assert Nonagon.interior_angles() == 1260# Example 3try:print('Before class')class Line(Polygon):print('Before sides')sides = 2print('After sides')print('After class')except:logging.exception('Expected')else:assert False# Example 4class BetterPolygon:sides = None # Must be specified by subclassesdef __init_subclass__(cls):super().__init_subclass__()if cls.sides < 3:raise ValueError('Polygons need 3+ sides')@classmethoddef interior_angles(cls):return (cls.sides - 2) * 180class Hexagon(BetterPolygon):sides = 6assert Hexagon.interior_angles() == 720# Example 5try:print('Before class')class Point(BetterPolygon):sides = 1print('After class')except:logging.exception('Expected')else:assert False# Example 6class ValidateFilled(type):def __new__(meta, name, bases, class_dict):# Only validate subclasses of the Filled classif bases:if class_dict['color'] not in ('red', 'green'):raise ValueError('Fill color must be supported')return type.__new__(meta, name, bases, class_dict)class Filled(metaclass=ValidateFilled):color = None # Must be specified by subclasses# Example 7try:class RedPentagon(Filled, Polygon):color = 'blue'sides = 5except:logging.exception('Expected')else:assert False# Example 8class ValidatePolygon(type):def __new__(meta, name, bases, class_dict):# Only validate non-root classesif not class_dict.get('is_root'):if class_dict['sides'] < 3:raise ValueError('Polygons need 3+ sides')return type.__new__(meta, name, bases, class_dict)class Polygon(metaclass=ValidatePolygon):is_root = Truesides = None # Must be specified by subclassesclass ValidateFilledPolygon(ValidatePolygon):def __new__(meta, name, bases, class_dict):# Only validate non-root classesif not class_dict.get('is_root'):if class_dict['color'] not in ('red', 'green'):raise ValueError('Fill color must be supported')return super().__new__(meta, name, bases, class_dict)class FilledPolygon(Polygon, metaclass=ValidateFilledPolygon):is_root = Truecolor = None # Must be specified by subclasses# Example 9class GreenPentagon(FilledPolygon):color = 'green'sides = 5greenie = GreenPentagon()assert isinstance(greenie, Polygon)# Example 10try:class OrangePentagon(FilledPolygon):color = 'orange'sides = 5except:logging.exception('Expected')else:assert False# Example 11try:class RedLine(FilledPolygon):color = 'red'sides = 2except:logging.exception('Expected')else:assert False# Example 12class Filled:color = None # Must be specified by subclassesdef __init_subclass__(cls):super().__init_subclass__()if cls.color not in ('red', 'green', 'blue'):raise ValueError('Fills need a valid color')# Example 13class RedTriangle(Filled, Polygon):color = 'red'sides = 3ruddy = RedTriangle()assert isinstance(ruddy, Filled)assert isinstance(ruddy, Polygon)# Example 14try:print('Before class')class BlueLine(Filled, Polygon):color = 'blue'sides = 2print('After class')except:logging.exception('Expected')else:assert False# Example 15try:print('Before class')class BeigeSquare(Filled, Polygon):color = 'beige'sides = 4print('After class')except:logging.exception('Expected')else:assert False# Example 16class Top:def __init_subclass__(cls):super().__init_subclass__()print(f'Top for {cls}')class Left(Top):def __init_subclass__(cls):super().__init_subclass__()print(f'Left for {cls}')class Right(Top):def __init_subclass__(cls):super().__init_subclass__()print(f'Right for {cls}')class Bottom(Left, Right):def __init_subclass__(cls):super().__init_subclass__()print(f'Bottom for {cls}')
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。