python学习-基础-面向对象编程(高级)

面向对象编程高级

  1. slots

# __slots__
# Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
# __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
# 除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。
class Student3(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

s1 = Student3() # 创建新的实例
s1.name = 'Michael' # 绑定属性'name'
s1.age = 25 # 绑定属性'age'
#s1.score = 99 # 绑定属性'score' 但是会报错 AttributeError: 'Student' object has no attribute 'score'。

  1. @property

# @property
# Python内置的@property装饰器就是负责把一个方法变成属性调用的
# 把一个getter方法变成属性,只需要加上@property就可以了,
# 此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值
class Student4(object):
    @property
    def score(self): 
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
s4 = Student4()
s4.score = 60
print(s4.score) # 60

# 利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution:
class Screen(object):
	"""docstring for Screen"""
	def __init__(self):
		super(Screen, self).__init__()
		# self.arg = arg
		self.resolution = 786432
	@property
	def width(self):
		return self._width
	@property
	def height(self):
		return self._height
	@property
	def resolution(self):
		return self._height * self._width
	@width.setter
	def width(self, val):
		self._isValidNumber(val)
		self._width = val
	@height.setter
	def height(self, val):
		self._isValidNumber(val)
		self._width = val
	# 检查错误
	def _isValidNumber(self, val):
		if not isinstance(val, (int, float)):
			raise ValueError('type error')
		elif val < 0:
			raise ValueError('must positive number')
  1. 多重继承

# 通过多重继承,一个子类就可以同时获得多个父类的所有功能。
class Animal1(object):
    pass

# 大类:
class Mammal(Animal):
    pass

class Bird(Animal):
    pass

# 功能类
class Runnable(object):
    def run(self):
        print('Running...')

class Flyable(object):
    def fly(self):
        print('Flying...')

# 各种动物: 多继承
class Dog(Mammal, Runnable):
    pass

class Bat(Mammal, Flyable):
    pass

class Parrot(Bird, Runnable):
    pass

class Ostrich(Bird, Flyable):
    pass

  1. MixIn

#MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,
#我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。
# class Dog3(Mammal, RunnableMixIn, CarnivorousMixIn):
#     pass
#     编写一个多进程模式的TCP服务
# class MyTCPServer(TCPServer, ForkingMixIn):
#     pass
#     多线程模式的UDP服务
# class MyUDPServer(UDPServer, ThreadingMixIn):
#     pass
#     
  1. 定制类

    • __str__
    • __repr__
    • __iter__
    • __getitem__
    • __getattr__( REST API 可以利用完全动态的__getattr__)
    • __call__
# __str__ 返回一个可以读懂字符串 Student object (name: Michael)
# __repr__() 返回程序开发者看到的字符串 <__main__.Student object at 0x109afb310>
# 通常__str__()和__repr__()代码都是一样的,所以,有个偷懒的写法:
class Student5(object):
	"""docstring for Student5"""
	def __init__(self, name):
		# super(Student5, self).__init__()
		self._name = name
	def __str__ (self):
		return 'Student object (name: %s)' % self._name
		__repr__ = __str__
print(Student5('Jack'))
		
# __iter__
# 如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,
# 然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
# __getitem__ 取下标
# __getattr__ 属性或方法不存在,取设置的默认值
class Fib1(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __getitem__(self, n): # 像数组一样可以用下标取值, 可以使用切片
        if isinstance(n, int): # n是索引
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice): # n是切片
            start = n.start
            stop = n.stop
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L
    def __getattr__(self, attr):
        if attr=='score':
            return 99
    def __next__(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration()
        return self.a # 返回下一个值
# REST API  可以利用完全动态的__getattr__,我们可以写出一个链式调用:	
class Chain(object):

    def __init__(self, path=''):
        self._path = path

    def __getattr__(self, path):
        return Chain('%s/%s' % (self._path, path))

    def __str__(self):
        return self._path

    __repr__ = __str__

print(Chain().status.user.timeline.list)

# __call__
# 一个对象实例可以有自己的属性和方法,当我们调用实例方法时,
# 我们用instance.method()来调用。能不能直接在实例本身上调用呢?在Python中,答案是肯定的。
# __call__()还可以定义参数
# 任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用
class Student6(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)
s6 = Student6('Mick')
print(s6())

# 我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象
# 通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
print(callable(Student3()))
  1. 枚举类

from enum import Enum, unique
DayT= Enum('one', ('A', 'b', 'C','D'))
# 通过枚举获取所有的成员
for t, member in DayT.__members__.items():
	print(t, '=>', member, ',', member.value)
# value属性则是自动赋给成员的int常量,默认从1开始计数。
# 如果需要更精确地控制枚举类型,可以从Enum派生出自定义类unique
# @unique装饰器可以帮助我们检查保证没有重复值。
@unique
class WeekDay (Enum):
	Sun = 0 # Sun的value被设定为0
	Mon = 1
	Tue = 3
	Wed = 2
for t, member in WeekDay.__members__.items():
	print(t, '=>', member, ',', member.value)
# Weekday.Mon Weekday['Tue'] Weekday(1)
# 
# 把Stu1的gender属性改造为枚举类型,可以避免使用字符串:
@unique
class Gender (Enum):
	"""docstring for  Gender"""
	Male = 0
	Female = 1
		
class Stu2(object):
	"""docstring for Stu1"""
	def __init__(self, name, gender):
		# super(Stu2, self).__init__()
		self.name = name
		self.gender = gender

bart = Stu2('Bart', Gender.Male)
print(bart.gender == Gender.Male)

  1. 元类

# type() ,type函数可以查看一个类型或变量的类型,也可以创建新的类型
# 要创建一个class对象,type()函数依次传入3个参数:

#class的名称;
#继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
#class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
# Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
# 
# metaclass
# 除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。metaclass,直译为元类,基本不会用到

猜你喜欢

转载自blog.csdn.net/u011342216/article/details/86088796
今日推荐