文章目录
面向对象与面向过程
类和对象的关系
构造函数
实例属相与实例方法
类对象
类属性
类方法
方法没有重载,方法的动态性
私有属性和私有方法(实现封装)
@property 装饰器
set方法和get方法
类的继承
类的重写
super()获得父类的定义
多态
组合
工厂模式
面向对象与面向过程
面向对象是将问题进行功能实现层的分解,比如造飞机,先分解为机翼 机身 发动机 控制系统 等等
面向过程是在考虑问题时跟偏向于执行步骤,是将问题分解为可逐步执行的命令,如造机翼,分解为制造机翼的各个步骤。
面向对象的思维偏向于顶层或者架构的设计,更多考虑问题都涉及哪些功能模块,各功能模块之间如何协同工作。
面向过程更偏向于执行者思维,更多考虑问题都有哪些步骤,根据步骤逐步实施。
对于简单问题,可直接面向过程思维设计。
对于复杂问题,则需要分解为多个功能模块,每个功能模块再向下细分为具体步骤逐步实施。
类和对象的关系
class Student:
#这是构造函数,名字固定,第一个参数为self
def __init__(self,name,age):
#定义实例属性
self.name=name
self.age=age
#定义实例方法
def name1(self):
print('{0}的年龄是:{1}'.format(self.name,self.age))
s1=Student('jack',18)
s1.name1()
类也是一种对象,类是定义对象的对象,通过类来定义数据类型的属性(变量)和方法(函数),将行为和状态进行打包。
构造函数
class Student:
# 这是构造函数,固定名字为__init__
def __init__(self,name,age):
self.name=name
self.age=age
定义规则:第一个参数必须为self,名称固定,构造函数通常用来初始化实例对象
通过“类名(参数列表)”调用构造函数。调用后,将创建好的对象返回给相应的变量。
实例属相与实例方法
创建新对象后会创建新的内存空间,内存空间中会创建class中定义的实例属性和实例方法,可以对新定义的对象添加属性,可以调用实例方法。
类对象
类是一种type对象,也可以通过变量引用类对象
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def name1(self):
print('{0}的年龄是:{1}'.format(self.name,self.age))
#s1=Student('jack',18)
#s1.name1()
ss2=Student
s1=ss2('jam','20')
s1.name1()
上例中,类对象Student ->ss2
通过ss2创建一个新对象s1
类属性
类属性在建立新对象时,类属性不属于新对象
class Student:
# 这是类属性
school='PKU'
count=0
def __init__(self,name,age):
# 这是实例属性
self.name=name
self.age=age
Student.count+=1
def name1(self):
print('{0}的年龄是:{1}'.format(self.name,self.age))
#s1=Student('jack',18)
#s1.name1()
ss2=Student
s1=ss2('jam','20')
s1.name1()
print('一共创建了{0}个对象'.format(Student.count))
运行结果
jam的年龄是:20
一共创建了1个对象
类方法
只从属于类对象的方法,可是:
@classmethod
def 类方法名
class Student:
school='PKU'
count=0
def __init__(self,name,age):
self.name=name
self.age=age
Student.count+=1
def name1(self):
print('{0}的年龄是:{1}'.format(self.name,self.age))
@classmethod
def printschool(cls):
print(cls.school)
Student.printschhol()
PKU
静态方法用于定义与类对象无关的方法
类方法无法调用self属性
方法没有重载,方法的动态性
python语言中方法的定义不能重名,如果重名,新定义的方法会覆盖之前定义的方法,也就是之前定义的方法没有作用
可以在定义类外定义方法,再将方法赋值给类的方法属性
class Person:
def work(self):
print('好好学习')
def play1(s):
print('玩游戏')
def work2(s):
print('好好学习,天天向上')
def play_game(s):
print('{0}在玩游戏'.format(s))
Person.play= play_game
p=Person()
print(hex(id(p)))
p.play()
Person.work=work2
p1=Person()
p.work()
0x28276d32588
<__main__.person object at>在玩游戏
好好学习,天天向上
上例中首先定义了play_game(s)方法,先将这个方法赋值给Person 类中的play方法,之后创建新对象p,新对象p即可以调用Person类中的play方法。注意在定义play_game(s)方法时需要增加一个参数s,用于接收对象的ID,对应于类对象里的方法需要包含参数(self)
私有属性和私有方法(实现封装)
class Employee:
def __init__(self, name, score):
self.name = name
# 定义私有属性
self.__score = score
# 定义私有方法
def __job(self):
print('test1')
e1 = Employee('jacky', 60)
print(e1.name)
# python中私有属性无法直接访问,可以通过_class__私有属性访问
print(e1._Employee__score)
# 调用私有方法,私有方法的调用与私有属性一样
e1._Employee__job()
@property 装饰器
可以将一个方法变为一个属性调用
class Employee:
@property
def salary(self):
print('running ...')
return 10000
e1=Employee()
print(e1.salary)
running ...
10000
set方法和get方法
不适用装饰器写set方法和get方法
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
def get_salary(self):
return self.__salary
def set_salary(self, salary):
if 1000 < salary < 20000:
self.__salary = salary
#print(self.__salary)
else:
print('数值超出范围')
e1=Employee('jack',2000)
print(e1.get_salary())
e1.set_salary(900)
print(e1.get_salary())
2000
数值超出范围
2000
这里调用set_salary()可以给将输入的数值赋值给私有属性__salary,在调用get_salary()方法时,如果传入的数值在范围内则输出,如果传入的数值超出范围则打印‘超出范围’
可以使用@property 达到相同的目的
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
@property
def salary(self):
return self.__salary
@salary.setter
def salary(self, salary):
if 1000 < salary < 20000:
self.__salary = salary
else:
print('数值超出范围')
e1=Employee('jacky',2000)
e1.salary=10000
print(e1.salary)
输出结果
10000
类的继承
python支持多重继承,一个子类可以继承多个父类。具体语法如下
class子类类明(父类1[,父类2,…])
object是所有子类的父类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_age(self):
print('age')
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age)
self.score = score
# 输出Student子类继承的所有父类
print(Student.mro())
s=Student('jack',20,100)
s.say_age()
print(s.name)
类的重写
在子类中可以命名相同的方法,对父类中的方法进行重写,重写方法后,新建对象则调用子类重写后的方法。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_age(self):
print('age:',self.age)
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age)
self.score = score
def say_age(self):
print('我的年龄是{0}'.format(self.age))
# 输出Student子类继承的所有父类
print(Student.mro())
s=Student('jack',20,100)
s.say_age()
print(s.name)
输出结果
10000
[, , ]
我的年龄是20
jack
super()获得父类的定义
class A:
def test1(self):
print('test1{0}'.format(self))
class B(A):
def test1(self):
super().test1()
# A.test1(self)
# 上面两个代码等价
print('B', self)
B().test1()
test1<__main__.b object at>
B <__main__.b object at>
使用super()方法可以获得父类的定义,这与在代码中显示地写出父类方法作用一致。
多态
多态是方法的多态,属性没有多态
多态两个必要条件,集成父类和重写方法
class Human:
def dinner(self):
print('该吃饭了')
class Chinese(Human):
def dinner(self):
print('chopsticks')
class English(Human):
def dinner(self):
print('folk')
class Indian(Human):
def dinner(self):
print('hand')
def manDinner(m):
if isinstance(m, Human):
m.dinner()
else:
print('no way')
manDinner(Chinese())
manDinner(Indian())
chopsticks
hand
多态需要集成相同父类,同时重写父类中的方法,在本例中,判断m是否为Human类,如果是,就调用多态子类中的dinner方法
组合
组合与集成的区别
‘is a’关系,使用继承(如上例)
‘has a’关系,使用组合,如手机包含cpu 屏幕
class computer:
def __init__(self,CPU,screen):
self.CPU=CPU
self.screen=screen
class CPU:
def cal(self):
print('calculation')
class screen:
def dis(self):
print('display')
CPU1=CPU()
screen1=screen()
Computer1=computer(CPU1,screen1)
Computer1.CPU.cal()
calculation
工厂模式
class carfactory:
def creatcar(self,brand):
if brand=='奔驰':
return Ben()
elif brand=='奥迪':
return Audi()
class Ben:
pass
class Audi:
pass
factory=carfactory()
c1=factory.creatcar('奔驰')
c2=factory.creatcar('奥迪')
print(c1)
print(c2)