面向对象
类
属性
和方法
的集合)对象
instance
、object
;是类的具象,是一个实体哲学
一切皆对象
数据
和操作
的封装面向对象三要素
Python类
class ClassName:
block
class
关键字大驼峰
命名类对象
,绑定到标识符ClassName
类对象及类属性
x
是类MyClass
的变量foo
是方法对象method,不是普通的函数对象function,一般要求至少有一个参数(可以是self,只是惯用标识符,可换名字)。self
指代当前实例本身实例化
a = MyClass()
__new__
→ 实例化后会自动调用初始化方法。__init__(self)
→ (return None)
,首个参数必须是self
,其他参数随意,可以不定义,在实例化后隐式调用实例对象instance
实例变量是每个实例独有的;类变量是类的变量,是类的所有实例共享的属性和方法
Python中每个对象都有不同的属性。函数、类都是对象,类的实例也是对象
self
实例变量和类变量
class Person:
age = 3
def __init__(self,name):
self.name = name
tom = Person('tom',22) # __init__() takes 2 positional arguments but 3 were given
tom = Person('tom') # 实例化,初始化
jax = Person('jax')
print(tom.name,tom.age) # tom 3
print(jax.name,jax.age) # jax 3
print(Person.age) # 3
Person.age = 30 # 赋值重新定义变量
print(Person.age,tom.age,jax.age) # 30 30 30
属性访问顺序
实例.__dict__[变量名]
和实例.变量名
都可以访问.
点号访问属性,先找自己的字典__dict__
;若没有,则通过属性__class__
找自己的类,然后去类中的字典__dict__
中找__dict__[变量名]
访问,则不用以上方式查找。此为指明使用字典的key
查找,不是属性查找装饰一个类
def add(name,cls):
cls.NAME = name # 动态增加类属性
def add_name(name='TOM'):
def wrapper(cls):
cls.NAME = name
return cls
return wrapper
@add_name(name='JAX') # Person = wrapper(Person)
class Person:
AGE = 3
print(Person.NAME) # JAX
print(Person.AGE) # 3
类方法
cls
可以直接操作类的属性,无法操作类的实例class Pe:
@classmethod
def class_method(cls):
print('class={0.__name__}({0})'.format(cls)) # class = Pe()
cls.h = 111
Pe.class_method()
print(Pe.__dict__) # {...}
静态方法
class P:
@classmethod
def class_method(cls):
print('class={0.__name__}({0})'.format(cls)) # class=P()
cls.h = 123
@staticmethod
def static_method():
print(P.h) # 123
P.class_method()
P.static_method()
print(P().static_method()) # None
print(P.__dict__) # {...}
self
),类调用时则不传入参数cls
)私有属性
class Person:
def __init__(self,name,age=11):
self.name = name
self.__age = age
def growup(self,i=1):
if i > 0 and i < 100:
self.__age += i
p1=Person('tom')
p1.growup(22) # 33
p1.__age=123
print(p1.__age) # 'Person' object has no attribute '__age'
_类名__变量名
’)class Person:
def __init__(self,name,age=11):
self.name = name
self.__age = age
def growup(self,i=1):
if i > 0 and i < 100:
self.__age += i
def getage(self):
return self.__age
p1 = Person('tom')
p1.__age = 25
print(p1.__age) # 25
print(p1.getage()) # 11
print(p1.__dict__) # {'name': 'tom', '_Person__age': 11, '__age': 25}
class Person:
def __init__(self,name,age=17):
self.name = name
self._age = age
tom = Person('Tom')
print(tom._age) # 17
print(tom.__dict__) # {'name': 'Tom', '_age': 17}
class P:
def __init__(self,name,age=15):
self.name = name
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self,age):
self.__age = age
@age.deleter
def age(self):
# del self.__age
print('del')
tom = P('Tom')
print(tom.age) # 15
tom.age = 23
print(tom.age) # 23
del tom.age # del
面向对象例题
method 1:普通类实现
import random
class RandomGen:
def __init__(self,start=1,stop=100,patch=10): # 实例化初始化,提供类属性
self.start = start
self.stop = stop
self.patch = patch
def generate(self):
return [random.randint(self.start, self.stop) for x in range(self.patch)]
a = RandomGen()
print(a.generate())
method 2:类方法,作为工具实现
import random
class RandomGen:
@classmethod # 类方法
def generate(self,start=1,stop=100,patch=10):
return [random.randint(start, stop) for x in range(patch)]
a = RandomGen()
print(a.generate())
method 3:生成器实现version 1
import random
class RandomGenerator:
def __init__(self,start=1,stop=100,patch=10): # 实例化初始化,提供类属性
self.start = start
self.stop = stop
self.patch = patch
self._gen = self._generate()
def _generate(self):
while 1:
yield random.randint(self.start, self.stop) # 返回一个随机数
def generate(self,count=0):
patch = self.patch if count<=0 else count # 指定生成的次数,未指定则用缺省值(类属性patch=10)
return [next(self._gen) for x in range(patch)] # 返回指定次数的随机数
a = RandomGenerator()
print(a.generate())
print(a.generate(5))
method 4:生成器实现version 2
import random
class RandomGenerator:
def __init__(self,start=1,stop=100,patch=10):
self.start = start
self.stop = stop
self.patch = patch
self._gen = self._generate()
def _generate(self):
while 1: # yield一批数据
yield [random.randint(self.start, self.stop) for _ in range(self.patch)]
def generate(self,count=0):
if count > 0: # 控制次数
self.patch = count
return next(self._gen)
a = RandomGenerator()
print(a.generate())
print(a.generate(5))
method 5:使用property
import random
class RandomGenerator:
def __init__(self, start=1, stop=100, patch=10):
self.start = start
self.stop = stop
self.patch = patch
self._gen = self._generate()
def _generate(self):
while 1:
yield [random.randint(self.start, self.stop) for _ in range(self.patch)]
def generate(self):
return next(self._gen)
@property
def patch(self):
return self._patch
@patch.setter
def patch(self,value):
self._patch = value
a = RandomGenerator()
print(a.generate())
a.patch = 5
print(a.generate())
import random
class RandomGen:
@classmethod # 类方法
def generate(self, start=1, stop=100, patch=10):
return [random.randint(start, stop) for x in range(patch)]
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
a = RandomGen()
points = [Point(x,y) for x, y in zip(a.generate(),a.generate())] # zip函数配对组成二维
for p in points:
print('({}):({})'.format(p.x, p.y),end = '\t')
继承
class 子类名(基类1[,基类2,...]):
block
object
(在Python3中object
是所有对象的根基类)class A:
pass
等价于
class A(object)
pass
__base__
# 类的基类__bases__
# 类的基类元组__mro__
#显示方法查找顺序,基类的元组mro()
# 同上,返回列表__subclasses__()
# 类的子类列表继承中的访问控制
实例的__dict__
→ 类__dict__
→ 父类__dict__
立即返回
,未找到则返回异常
公有的
,子类和实例都可以访问
;私有的
,子类和实例不可直接访问
,但私有变量所在的类内的方法中可以访问这个私有变量方法的重写覆盖
super()
可以访问到父类的属性class Animal:
def shout(self):
print('Animals shouts')
class Cat(Animal):
# 覆盖了父类方法
def shout(self):
print('miao')
# 覆盖了自身的方法,显式调用了父类的方法
# super()可以访问到父类的属性
def shout(self):
print(super()) # , >
print(super(Cat, self)) # , >
super().shout()
super(Cat,self).shout() # Animals shouts ,等价于super()
a = Animal()
a.shout() # Animals shouts
c = Cat()
c.shout() # miao
print(a.__dict__) # {}
print(c.__dict__) # {}
print(Animal.__dict__) # {'__module__': '__main__', 'shout': , '__dict__': , '__weakref__': , '__doc__': None}
print(Cat.__dict__) # {'__module__': '__main__', 'shout': , '__doc__': None}
class A:
def __init__(self,age):
print('A init')
self.age = age
def show(self):
print(self.age)
class B(A):
def __init__(self,age,w):
# 调用父类的__init__方法顺序决定show方法的结果
super().__init__(age) # A.__init__(age)
print('B init')
self.age = age + 1
self.w = w
b = B(10,5)
b.show()