标签:多继承 多态 classname 额外 pre 情况下 slow book python2
在类的命名空间里 :静态变量,绑定方法
在对象的明敏空间里: 类指针,对象的属性(实例变量)
静态变量:类中的变量就是静态变量
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
? 和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
语法格式如下:
class ClassName:
<statement-1>
.
.
.
<statement-N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
? 属性引用和实例化。
? 属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return ‘hello world‘
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
# 以上创建了一个新的类实例并将该对象赋给局部变量 x,x 为空的对象。执行以上程序输出结果为:
# MyClass 类的属性 i 为: 12345
# MyClass 类的方法 f 输出为: hello world
类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用,像下面这样:
def 类名:
#初始化函数,用来完成一些默认的设定
def __init__():
pass
在创建一个对象时默认被调用,不需要手动调用
__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形 参,例如__init__(self,x,y)
__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去
类定义了 __init__() 方法,类的实例化操作会自动调用 __init__() 方法。如下实例化类 MyClass,对应的 __init__() 方法就会被调用:
x = MyClass()
当然, __init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上。例如:
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
# 以上实例执行结果为:
# <__main__.Test instance at 0x100771878>
# __main__.Test
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
class Test:
def prt(runoob):
print(runoob)
print(runoob.__class__)
t = Test()
t.prt()
# 以上实例执行结果为:
# <__main__.Test instance at 0x100771878>
# __main__.Test
class people:
#定义基本属性
name = ‘‘
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people(‘runoob‘,10,30)
p.speak()
# 执行以上程序输出结果为:
# runoob 说: 我 10 岁。
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
struct_t = time.localtime()
date = cls(struct_t.tm_year, struct_t.tm_mon, struct_t.tm_mday)
return date
date = Date.today()
print(date.year) # 2020
print(date.month) # 6
print(date.day) # 4
class Classname:
@staticmethod
def fun():
print(‘静态方法‘)
C = Classname()
Classname.fun()
C.fun()
class Method:
method = ‘静态变量‘ # 所有对象共享的变量 由对象/类调用,不能重新赋值
class Method:
method = ‘静态变量‘ # 所有对象共享的变量 由对象/类调用,不能重新赋值
def func(self): # 自带self参数的函数 由对象调用
print("绑定方法")
@classmethod
def Cls_func(cls): # 自带cls参数的函数,由对象/类调用
print(‘类方法‘)
@staticmethod
def static_func(): # 普通函数 不带参数的函数,由对象/类调用
print(‘静态方法‘)
@property
def hello(self): # property属性 是个伪装成属性的方法,由对象调用,不加括号
return ‘Hello‘
__init__ : 构造函数,在生成对象时调用
__call__: 函数调用
__len__: 获得长度
__repr__ : 打印,转换
__eq__: 相等,判断两个对象是否相等,执行(a == b)时会调用__eq__()方法
__gt__: 判断大于
__lt__: 判断小于
__del__ : 析构函数,释放对象时使用
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__cmp__: 比较运算
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__truediv__: 除运算
__mod__: 求余运算
__pow__: 乘方
def __init__(self,name,age):
print("----------------->init")
self.name = name
self.age = age
def __call__(self,name):
print("This is a function",name)
def __len__(self):
return len(self.name)
触发时机:在实例化时触发,(在创建一块对象空间时,有一个指针指向类,会先调用__new__(),再调用__init__())
用途:设计模式中的单例模式
def __new__(cls,*args,**kwargs): # 向内存要空间 --> 地址
print("------------->new")
return object.__new__(cls)
def __str__(self):
return "对象名字是:" + self.name + ",年龄是:" + str(self.age)
触发机制:类似__str__(),str(对象)总是调用对象的__str__方法,如果类中有__str__,优先返回__str__的内容,没有在根据__repr__()的内容返回
如果想直接返回__repr__()中的内容,可以使用 %r 字符串拼接,或者repr(对象)
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name
def __repr__(self):
return self.name + ‘,年龄:‘ + str(self.age)
student = Student(‘张三‘, 18)
print(str(student)) # 张三
print(‘学生:%s‘ % student) # 学生:张三
print(repr(student)) # 张三,年龄:18
print(‘学生:%r‘ % student) # 学生:张三,年龄:18
Python同样支持运算符重载,我们可以对类的专有方法进行重载,实例如下:
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return ‘Vector (%d, %d)‘ % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
# 以上代码执行结果如下所示:
# Vector(7,8)
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有对象属性或方法(私有实例变量),self.__age = 18就是私有属性,而self.age = 18就不是私有属性,同样def __secret(self):是私有绑定方法,def secret(self):不是私有方法
class Women:
def __init__(self, name):
self.name = name
# 不要问女生的年龄
self.__age = 18
def __secret(self):
print("我的年龄是 %d" % self.__age) # 在类内部使用时,自动把类的名字拼接在私有变量前完成变形
xiaofang = Women("小芳")
# 私有属性,外部不能直接访问
# print(xiaofang.__age)
# 私有方法,外部不能直接调用
# xiaofang.__secret()
class Foo(object):
def __init__(self):
self.__func() # __func()已经被类内部改名为_Foo__func()
def __func(self):
print(‘in Foo‘)
class Son(Foo): # 初始化时到父类找__init__方法,调用的是_Foo__func()
def __func(self): # __func()已经被改名为:_Son__func()
print(‘in Son‘)
Son() # in Foo
? 访问对象的 私有属性 或 私有方法Python 中,并没有 真正意义 的 私有,在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到,处理方式:在 调用的属性名或者方法名称 前面加上 _类名 => _类名__名称,在日常开发中,不要使用这种方式,
class Women:
def __init__(self, name):
self.name = name
# 不要问女生的年龄
self.__age = 18
def __secret(self):
print("我的年龄是 %d" % self.__age)
xiaofang = Women("小芳")
# 私有属性,外部不能直接访问(加上`_Women`就可以了)
# print(xiaofang._ Women__age)
# 私有方法,外部不能直接调用(加上`_Women`就可以了)
# xiaofang._Women__secret()
# 提示
# print(xiaofang.__age) => print(xiaofang._ Women__age)
# xiaofang.__secret() => xiaofang._Women__secret()
例一:
class Goods:
discount = 0.8
def __init__(self, origin_price):
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.setter
def price(self, new_price):
self.__price = new_price
return self.__price
goods = Goods(10)
print(goods.price) # 8.0 调用的是被@property装饰的price
goods.price = 12 # 调用的是被setter装饰的price
print(goods.price)
class Goods:
discount = 0.8
def __init__(self, origin_price):
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.deleter
def price(self, new_price):
del self.__price
goods = Goods(10)
del goods.price # 并不能真正删除什么,只是调用@price.deleter函数
def setAge(self,age):
self.__age = age
def getAge(self):
return self.__age
@property
def age(self):
return self.__age
@age.setter
def age(self,age):
If age>0 and age<=120:
self.__age = age
else:
print("输入不符合要求!")
has-a说的是一种包含关系,意思是说父类包含子类,比如人和心脏的关系,心脏属于人,但心脏并不是人。
# 学生类Student 和 书类Book
class Student:
def __init__(self,name,book):
self.name = name
self.book = book
class Book:
def __init__(self,name,author):
self.name = name
self.author = author
# 学生类中有book,学生和书直接的关系就是has a
is-a的意思是说:子类即父类。也就是子类在继承父类之后,并没有做任何异于父类的操作,比如并未添加新的内容。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("{}正在吃饭.....".format(self.name))
class Doctor(Person):
pass
class Employee(Person):
pass
is-like-a的意思是说:子类继承父类,但是有添加了新的内容,子类并不完全等同于父类,而是与父类相似。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("{}正在吃饭.....".format(self.name))
class Student(Person):
def __init__(self,name,age,clazz):
super().__init__(name,age) # 继承父类的__init__方法,重写子类__init__
self.clazz = clazz
def number(self):
print("班级名为:",self.clazz)
s = Student("Jack",18,"本计153班")
s.eat()
s.number()
class P1:
def foo(self):
print("p1---foo")
class P2:
def foo(self):
print("p2---foo")
def bar(self):
print("p2---bar")
class C1(P1,P2):
pass
class C2(P1,P2):
def bar(self):
print("c2---bar")
class D(C1,C2):
pass
?
? 也可以写super(D,self).func()
class User:
def __init__(self, name):
self.name = name
class VIPUser(User):
def __init__(self, name, level):
# super().__init__(name) # 推荐
super(VIPUser, self).__init__(name)
self.level = level
class Payment: # 抽象类 约束子类必须拥有重名方法
def pay(self, money):
raise NotImplementedError("没有实现相应的支付方法")
class WeChat(Payment):
def __init__(self, name):
self.name = name
def fuqian(self, money):
print(f"{self.name}支付了{money}")
def cost(name, price, kind):
if kind == "wechat":
wechat = WeChat(name)
wechat.pay(price)
cost(‘Jack‘, 200, ‘wechat‘) # 会抛出异常
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 约束子类必须拥有重名方法
@abstractmethod
def pay(self, money):
pass
class WeChat(Payment):
def __init__(self, name):
self.name = name
def fuqian(self, money):
print(f"{self.name}支付了{money}")
def cost(name, price, kind):
if kind == "wechat":
wechat = WeChat(name)
wechat.pay(price)
cost(‘Jack‘, 200, ‘wechat‘)
将同名功能进行统一调用
class A:
def 同名功能(self):
pass
class B:
def 同名功能(self):
pass
def 函数名(obj):
obj.同名功能()
支付表现出微信支付和苹果支付
在java中:一个参数必须制定类型,所以想让两个类型的对象多可以传,那么必须让两个类基础自一个父类,在确定类型时使用父类来指定。
a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型
isinstance(a, list) # True
isinstance(b, Animal) # True
isinstance(c, Dog) # True
# 看来a、b、c确实对应着list、Animal、Dog这3种类型。
isinstance(c, Animal) # True
c不仅仅是Dog,c还是Animal!因为Dog是从Animal继承下来的,当创建了一个Dog的实例c时,认为c的数据类型是Dog没错,但c同时也是Animal也没错,Dog本来就是Animal的一种!
在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:
b = Animal()
isinstance(b, Dog) # False
Dog可以看成Animal,但Animal不可以看成Dog。
要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个Animal类型的变量:
def run_twice(animal):
animal.run()
animal.run()
# 当我们传入Animal的实例时:
run_twice(Animal())
# run_twice()就打印出
# Animal is running...
# Animal is running...
# 当我们传入Dog的实例时:
run_twice(Dog())
# run_twice()就打印出
# Dog is running...
# Dog is running...
当我们传入Cat的实例时:
run_twice(Cat())
# run_twice()就打印出
# Cat is running...
# Cat is running...
# 如果我们再定义一个Tortoise类型,也从Animal派生:
class Tortoise(Animal):
def run(self):
print(‘Tortoise is running slowly...‘)
# 当我们调用run_twice()时,传入Tortoise的实例:
run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...
# 会发现,新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。
形似:只要它走路像鸭子,有脚蹼,...那它就是鸭子类型
定义:满足特定的约定,就是鸭子类型
tupel:元组类 是可以哈希的,又不依赖继承哈希类来判定是不是可哈希类型,元组类是可哈希类型的鸭子类型
所有实现了__len__方法的类,在调用len函数的时候,obj就说是鸭子类型
迭代器协议: 拥有 __iter__ __next__ 的方法就是迭代器
子类继承父类,子类也是父类这个类型
Python中一个类是不是属于某一个类型,不仅仅可以通过继承来完成
还可以不继承,但如果这个类满足了某些类型的特征条件,我们就说它长得像某个类型,那它就是这个类型的鸭子类型
标签:多继承 多态 classname 额外 pre 情况下 slow book python2
原文地址:https://www.cnblogs.com/q121211z/p/13384305.html