类、对象及其简单示例
类:具有相同属性和技能的一类事物。将一个类实例化,就得到了对象。
class Person:
# 静态变量,静态字段
mind = "华山大弟子"
animal = "高级动物"
def __init__(self):
pass
# 方法,动态变量
def func(self):
print("函数")
# 从类名角度
# 静态字段
print(Person.__dict__) # 查看类中的全部内容
{'__module__': '__main__', 'mind': '华山大弟子', 'animal': '高级动物', '__init__': <function Person.__init__ at 0x00000273BA54CEA0>, 'func': <function Person.func at 0x00000273BA54CE18>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
print(Person.mind) # 查看
Person.money = "货币" # 增加静态字段
print(Person.money)
华山大弟子
货币
Person.animal = "高级高级高级动物" # 修改静态变量
print(Person.animal)
高级高级高级动物
del Person.mind # 删除
print(Person.__dict__)
{'__module__': '__main__', 'animal': '高级高级高级动物', '__init__': <function Person.__init__ at 0x00000273BA54CEA0>, 'func': <function Person.func at 0x00000273BA54CE18>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'money': '货币'}
# 操作类中的方法,除了类方法,静态方法,需要类名调用之外,剩下的方法都要对象调用
class Person:
# 静态变量,静态字段
mind = "华山大弟子"
animal = "高级动物"
def __init__(self,name,money):
self.name = name
self.money = money
# 方法,动态变量
def func(self):
print("函数")
obj = Person("华山大弟子",1000) # 产生示例传给obj
print(obj.name)
华山大弟子
# 查询对象空间的全部内容
print(obj.__dict__)
{'name': '华山大弟子', 'money': 1000}
组合
class GameRole:
def __init__(self,name,sex,age,ad,hp):
self.name = name
self.sex = sex
self.age = age
self.ad = ad
self.hp = hp
def attack(self,p):
p.hp = p.hp - self.ad
print('%s赤手空拳打了%s%s滴血,%s还剩%s血' %(self.name,p.name,self.ad,p.name,p.hp))
def add_moto(self,mo):
self.mo = mo
def add_weapon(self,wea):
self.wea = wea
def road_rush(self,p1):
p1.hp = p1.hp - self.ad - self.wea.ad
print('%s骑着%s打了骑着%s的%s一%s,%s哭了,还剩%s血' \
%(self.name,self.mo.name,p1.mo.name,p1.name,self.wea.name,p1.name,p1.hp))
class Weapon:
def __init__(self,name,ad):
self.name = name
self.ad = ad
def fight(self,p1,p2):
p2.hp = p2.hp - p1.ad - self.ad
# print(' %s利用%s打了%s一%s,%s还剩%s血' %(p1.name,self.name,p2.name,self.name,p2.name,p2.hp))
print('{0}利用{1}打了{2}一{1},{2}还剩{3}血'.format(p1.name,self.name,p2.name,p2.hp))
class Moto:
def __init__(self,name,speed):
self.name = name
self.speed = speed
def drive(self,p1):
print('%s骑着%s开着%d迈的车行驶在赛道上' % (p1.name,self.name,self.speed))
p1 = GameRole('小姐姐','女',18,20,200)
p2 = GameRole('小哥哥','男',20,30,150)
p3 = GameRole('大姐姐','女',19,50,80)
w1 = Weapon('平底锅',20)
w2 = Weapon('斧子',50)
w3 = Weapon('双节棍',65)
m1 = Moto('小踏板',60)
m2 = Moto('雅马哈',80)
m3 = Moto('宝马',120)
p1.add_moto(m3)
p1.add_weapon(w3)
p2.add_moto(m2)
p1.road_rush(p2)
小姐姐骑着宝马打了骑着雅马哈的小哥哥一双节棍,小哥哥哭了,还剩65血
# 定义一个类,计算圆的面积
class Circle:
def __init__(self,r):
self.pi = 3.1415
self.r = r
def area(self):
return self.r**2*self.pi
def permeter(self):
return self.r*2*self.pi
c1 = Circle(3)
print(c1.area(),c1.permeter())
28.273500000000002 18.849
# 定义一个圆环,计算圆环的面积和周长
class ring :
def __init__(self,r1,r2):
self.pi = 3.1415
self.r1 = r1
self.r2 = r2
def area(self):
return self.r1**2*self.pi - self.r2**2*self.pi
def permeter(self):
return self.r1*2*self.pi - self.r2*2*self.pi
r = ring(6,4)
print(r.area(),r.permeter())
62.830000000000005 12.565999999999999
继承
(1)调用父类构造函数
(2)方法重写,重写父类中的方法
class Parent: # 定义父类
def __init__(self):
print("我是父类构造函数")
def myMethod(self):
print("调用父类方法")
class Child(Parent): # 定义子类
def __init__(self):
super().__init__() ## 调用父类的构造方法
print("我是子类构造方法")
def myMethod(self): # 重写父类的方法
print('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
我是父类构造函数
我是子类构造方法
调用子类方法
限制性父类中的myMethod方法再执行子类的myMethod方法
class Parent: # 定义父类
def __init__(self):
print("我是父类构造函数")
def myMethod(self):
print("调用父类方法")
class Child(Parent): # 定义子类
def __init__(self):
super().__init__() ## 调用父类的构造方法
print("我是子类构造方法")
def myMethod(self): # 重写父类的方法
super().myMethod()
print('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
我是父类构造函数
我是子类构造方法
调用父类方法
调用子类方法
类:经典类和新式类
新式类:凡是继承object类都是新式类(Python3版本中所有的类都是新式类,都默认继承了object类。class A = classA(object))
经典类:不继承object类的都是经典类,经典类只存在于Python2版本中。python2默认不继承object类。
继承:单继承和多继承
单继承:新式类,经典类查询顺序一样
多继承:新式类:遵循广度优先;经典类:遵循广度优先
# 多继承的新式类
class A:
def func(self):
print("in A")
class B(A):
def func(self):
print("in B")
class C(A):
def func(self):
print("in C")
class D(B):
def func(self):
print("in D")
class E(C):
def func(self):
print("in E")
class F(D,E):
def func(self):
print("in F")
f1 = F()
f1.func()
in F
class A:
def func(self):
print("in A")
class B(A):
def func(self):
print("in B")
class C(A):
def func(self):
print("in C")
class D(B):
def func(self):
print("in D")
class E(C):
def func(self):
print("in E")
class F(D,E):
pass
# def func(self):
# print("in F")
f1 = F()
f1.func()
in D
class A:
def func(self):
print("in A")
class B(A):
def func(self):
print("in B")
class C(A):
def func(self):
print("in C")
class D(B):
pass
# def func(self):
# print("in D")
class E(C):
def func(self):
print("in E")
class F(D,E):
pass
# def func(self):
# print("in F")
f1 = F()
f1.func()
in B
class A:
def func(self):
print("in A")
class B(A):
pass
# def func(self):
# print("in B")
class C(A):
def func(self):
print("in C")
class D(B):
pass
# def func(self):
# print("in D")
class E(C):
def func(self):
print("in E")
class F(D,E):
pass
# def func(self):
# print("in F")
f1 = F()
f1.func()
in E
class A:
def func(self):
print("in A")
class B(A):
pass
# def func(self):
# print("in B")
class C(A):
def func(self):
print("in C")
class D(B):
pass
# def func(self):
# print("in D")
class E(C):
pass
# def func(self):
# print("in E")
class F(D,E):
pass
# def func(self):
# print("in F")
f1 = F()
f1.func()
in C
class A:
def func(self):
print("in A")
class B(A):
pass
# def func(self):
# print("in B")
class C(A):
pass
# def func(self):
# print("in C")
class D(B):
pass
# def func(self):
# print("in D")
class E(C):
pass
# def func(self):
# print("in E")
class F(D,E):
pass
# def func(self):
# print("in F")
f1 = F()
f1.func()
in A
上述继承关系如下钻石搜索(层次遍历)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Zo5xLg1-1588040851273)(attachment:image.png)]
小结:
继承使得类与类之间发生关系,而组合则使得对象与对象之间发生关系。
子类中即实现父类的方法,又实现自己的方法:
super().父类方法名(参数(自传self))
父类名.父类方法名(参数)
经典类不继承object,新式类默认继承object。
经典类深度优先继承,新式类广度优先遍历。
抽象类、接口类
接口类和抽象类在java中是两个不同的东西。但在Python中其实是一样的。
Python没有多态但是有多继承,java没有多继承但是有多态。
Python中没有接口这个概念。
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类接口,定义开发规范
@abstractmethod # 装饰器,继承的类必须有pay方法!!!
def pay(self):
pass
class Alipay(Payment):
def __init__(self,money):
self.money = money
def pay1(self):
print("使用支付宝支付%s"%(self.money))
a1 = Alipay(100)
a1.pay1()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-c35b7c62a951> in <module>()
9 def pay1(self):
10 print("使用支付宝支付%s"%(self.money))
---> 11 a1 = Alipay(100)
12 a1.pay1()
TypeError: Can't instantiate abstract class Alipay with abstract methods pay
from abc import ABCMeta,abstractmethod
# 强制制定一个规范,凡是继承我的类中必须有pay()方法,如果没有,实例化的时候回报错。
class Payment(metaclass=ABCMeta): # 抽象类接口,定义开发规范
@abstractmethod # 装饰器,继承的类必须有pay方法
def pay(self):
pass
class Alipay(Payment):
def __init__(self,money):
self.money = money
def pay(self):
print("使用支付宝支付%s"%(self.money))
a1 = Alipay(100)
a1.pay()
使用支付宝支付100
多态
Python面向对象的三大特征之一:
多态:Python处处是多态.
Python是弱类型语言 name = 666
java是强类型语言 int i = 5;
# Python不管什么类型,传入函数,封装到对象中都可以。
def func(a):
print(a)
func([1,2,3,4,56])
func(111)
[1, 2, 3, 4, 56]
111
封装
实例化一个对象,给帝乡空间封装一些属性,这就是广义上的封装。
那么什么是狭义的封装呢?
将对象进行私有制,如一些私有的成员:私有静态字段、私有方法、私有对象属性。
class A:
name = "华山大弟子"
def func(self):
print("func函数")
a1 = A()
a1.name
'华山大弟子'
class A:
__name = "华山大弟子"
def func(self):
print("func函数")
a1 = A()
a1.__name #实例化对象不能访问私有静态字段
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-110f405a238b> in <module>()
4 print("func函数")
5 a1 = A()
----> 6 a1.__name
AttributeError: 'A' object has no attribute '__name'
class A:
__name = "华山大弟子"
def func(self):
print("func函数")
a1 = A()
A.__name #类本身不能访问私有静态字段
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-10-a432ca275fea> in <module>()
4 print("func函数")
5 a1 = A()
----> 6 A.__name #实例化对象不能访问私有静态字段
AttributeError: type object 'A' has no attribute '__name'
class A:
__name = "华山大弟子"
def func(self):
print(self.__name) # 对于私有静态变量,类的内部可以访问
print(A.__name)
print("func函数")
a1 = A()
a1.func()
华山大弟子
华山大弟子
func函数
class B:
__money = 10000000
class C(B):
name = "华山大弟子"
__age = 20
def func(self):
print(self.__money)
print("func......")
c1 = C
c1.func()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-53ef440fd8fd> in <module>()
8 print("func......")
9 c1 = C
---> 10 c1.func()
TypeError: func() missing 1 required positional argument: 'self'
小结
对于私有静态字段来说,只能在本类内部访问,类的外部、派生类均不可访问。
对于私有方法来说,
# 有方法可以访问,但是工作中千万不能使用
class B:
__money = 10000000
class C(B):
name = "华山大弟子"
__age = 20
def func(self):
print(self._B__money) # 其实在Python在内存中将私有静态变量名字加上了“_”“类名”和变量名。工作中千万不要这么用!!!
print("func......")
c1 = C()
c1.func()
10000000
func......
class B:
__money = 10000000
class C(B):
name = "华山大弟子"
def __func(self):
print("---")
c = C()
c.__func()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-24-a0f9a8859926> in <module>()
6 print("---")
7 c = C()
----> 8 print(c.__func())
AttributeError: 'C' object has no attribute '__func'
class B:
__money = 10000000
class C(B):
name = "华山大弟子"
def __func(self):
print("---")
c = C()
c._C__func() # 利用漏洞可以访问,工作中千万不要这么搞,会被当做野生程序员的......
---
None
class B:
__money = 10000000
def __func1(self):
print("in B")
class C(B):
name = "华山大弟子"
def func(self):
print("---")
self.__func1()
c = C()
c.func() # 类的派生类也不能访问,私有方法,只有在类自己本身。。。。因为在私有方法前面加了前缀
---
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-28-d7b8780584b0> in <module>()
9 self.__func1()
10 c = C()
---> 11 c.func()
<ipython-input-28-d7b8780584b0> in func(self)
7 def func(self):
8 print("---")
----> 9 self.__func1()
10 c = C()
11 c.func()
AttributeError: 'C' object has no attribute '_C__func1'
属性property
class Person:
def __init__(self,name,hight,weight):
self.name = name
self.__hight = hight
self.__weight = weight
def bmi(self):
return "%s的bmi值是%s"%(self.name,self.__weight/self.__hight**2)
p1 = Person("华山大弟子",1.78,72)
p1.bmi()
'华山大弟子的bmi值是22.724403484408533'
# 添加一个装饰器,将函数转变为属性
# property修改了函数的调用方式。将一个方法伪装成一个属性,在代码级别并没有啥本质区别,
# 只是看起来更加合理。
class Person:
def __init__(self,name,hight,weight):
self.name = name
self.__hight = hight
self.__weight = weight
@property
def bmi(self):
return "%s的bmi值是%s"%(self.name,self.__weight/self.__hight**2)
p1 = Person("华山大弟子",1.78,72)
p1.bmi # 已经伪装成属性了
'华山大弟子的bmi值是22.724403484408533'
# 触发模式
class A:
def __init__(self,name,age):
self.name = name
self.__age = age
@property
def age(self):
return self.__age
@age.setter # setter触发器是属性中带的方法
def age(self,age1):
print(age1)
print("in age(self,age1)")
a1 = A("华山大弟子",20)
print(a1.age)
a1.age = 10000
20
10000
in age(self,age1)
类方法和静态方法
类方法:通过类名调用的方法,类方法中第一个参数约定俗成为cls,python自动将类空间传给cls。当方法不需要对象参与的时候可以使用。
对类中的静态变量需要进行改变,需要使用类方法。继承中,父类得到子类的类空间。
# 类方法
class A:
def func(self):
print(self)
@classmethod # 类方法
def func1(cls):
print(cls)
a1 = A()
a1.func()
A.func1()
a1.func1() # 对象和类都可以调用,得到的都是类本身
<__main__.A object at 0x000001B2D22ADDA0>
<class '__main__.A'>
<class '__main__.A'>
# 当方法不需要对象参与的时候可以使用
class A:
name = "华山大弟子"
count = 1
@classmethod
def func(cls): # 此方法无需对象参与
return cls.name+str(cls.count)
A.func()
'华山大弟子1'
# 继承中,父类得到子类的类空间
class A:
name = "华山大弟子"
count = 1
@classmethod
def func(cls): # 此方法无需对象参与
return cls.name+str(cls.count)
class B(A):
pass
B.func()
'华山大弟子1'
class A:
age = 18
@classmethod
def func(cls): # 此方法无需对象参与
return cls.age
class B(A):
age=17
B.func()
17
静态方法
好处:1、使代码看起来结构清晰;
class A:
@staticmethod
def func():
print("我是静态方法")
A.func()
a = A()
a.func()
我是静态方法
我是静态方法
内置函数
# isinstance() 用该方法去判断的时候,子类的对象即是子类对象也是父类对象
# 如果用type()判断的是子类。如果不想判断继承关系就用type(obj) is 类名。
class A:
pass
class B(A):
pass
b = B()
print(isinstance(b,A))
print(isinstance(b,B))
True
True
# == 判断值相等,值运算;is内存地址相等,身份相等。is要求更苛刻,不仅要求值相等,还要求内存地址相同。
a = 1111
b = 1111
print(id(a))
print(id(b))
print(a==b)
print(a is b)
1341327237744
1341327237776
True
False
# issubclass() 判断类与类之间的继承关系
class Animal:
pass
class Cat(Animal):
pass
class Person(Animal):
pass
issubclass(Cat,Animal) # 判断Cat是不是Animal的子类
True
两个内置函数 *
反射 ******
方法:getattr、hasattr、setattr、delattr
用字符串数据类型的变量名来访问这个变量的值
内置方法 ***
# 反射的使用
# 使用类放射
## 原始的方法
# class Student:
# def __init__(self):pass
# def look_course(self):
# print("查看课程")
# def choose_course(self):
# print("选择课程")
# def choosed_course(self):
# print("查看已选课程")
# student = Student()
# num = "look_course"
# if num == "look_course":
# student.look_course()
# 反射
class Student:
ROLE = "Student"
score = 100
@classmethod
def check_score(cls):
print(cls.ROLE)
print(cls.score)
print("检查分数!!!")
@staticmethod
def login():
print("登陆")
user_input = "ROLE"
# eval 这个东西 明确的写在你的代码里才可以用
# 反射查看属性
getattr(Student,user_input) # 用字符串的变量名来拿到变量值
# 发射调用方法
getattr(Student,"check_score")()
# 反射调用静态方法
getattr(Student,"login")()
# hasattr 判断是否存在该方法
print(hasattr(Student,"huashan"))
print(hasattr(Student,"login"))
Student
100
检查分数!!!
登陆
False
True
x = 7
eval("3**x") # 不安全
2187
# 使用对象反射
class A:
def __init__(self,age):
self.age = age
def func(self):
print("func 函数")
a = A(10)
print(getattr(a,"age"))
getattr(a,"func")()
10
func 函数
# 反射自己模块中的内容
# import相当于导入了一个模块,模块哪个导入哪个没导入,在python的
# 解释器汇总记录
import os
print(getattr(os,"rename"))
<built-in function rename>
反射
hasattr、getattr
类名.名字 getattr(类名,名字)
对象名.名字 getattr(对象名,名字)
模块名.名字 getattr(模块,名字)
自己文件.名字
import sys
getattr(sys.modules(“main”),‘名字’)