面向过程
title = 'Python入门'
price = 39.02
author = 'prter'
def search_book0(title):
pass
'''面向过程,都是些很松散的变量、表达式、函数
所以要想办法将松散的字段(有关联的)封装到一个类/对象里,将一些行为封装到函数里也是封装'''
使用Python内置的对象进行代码封装
1、将这些字段放入列表
book = [title, price, author, search_book0]
2、用字典表的方法模拟面向对象,字典表是初期没有学习面向对象时作为封装的最佳选择
def search_book(title):
print('搜索包含关键词[{}]的图书:'.format(title))
book = {
'title': 'Python入门',
'price': 39.02,
'author': 'prter',
'search_book': search_book
}
book.get('search_book')('啦啦啦') # 间接调用了search_book这个函数,委托
book['search_book']('lalala')
print(book['title'])
print(book.get('price', 0.0))
面向对象:基础
定义类 和 实例化对象
class Book: # 定义类的时候类名要大写
pass # 什么不写放个占位符就行
book = Book() # 实例化
# 实例化后 同时定义对象的属性和值
book.title = 'Python入门'
book.price = 39.02
book.author = '旧人'
print(book.title)
print(book.price)
print(book.author)
# 这种方式还是很松散
面向对象1
定义类 实例化对象 真正符合语法的
import datetime # 导入这个处理时间的模块
class Book: # __init__(self)构造函数 初始化类成员
def __init__(self, title, price=0.0, author='', publisher=None, pubdate=datetime.date.today()):
self.title = title # 定义了五个成员属性 分别指向上面的形参 实例化的时候传递的实参是它实际的值
self.price = price # 如果属性名是两个_开头的是私有成员属性 如:self.__price
self.author = author
self.publisher = publisher
self.pubdate = pubdate
# self类似其他语言的this 但是有些编程语言self和this有区别
# 会有很多不同的实例来通过self调用这些属性
# self不能理解为class Book的本身 谁调用它 它就指向谁 跟this很像
# 定义在交互式提示符下 输入实例后的对象的显示
# 不定义默认输出:<main3.Book object at 0x03224D30> 对于用户和开发人员来说没什么意义
def __repr__(self):
return '<图书 {} 定价 {} at 0x{}>'.format(self.title, self.price, id(self))
# self.title 是获取当前图书的书名
# self获取当前图书 使用id这个全局函数得到当前图书在内存里的id
# 现在输出的就是 <图书 C#精典 定价 22.9 at 0x51488496> 这种样子
def __str__(self):
return '[图书:{} 定价:{}]'.format(self.title, self.price)
# __repr__ 是定义开发者在控制台上直接输入实例后的对象名称时打印的结果
# __str__ 是用print()打印时显示的结果 本质上一样的 不定义这个默认拿__repr__代替
def print_info(self): # 在类里定义一个自己的打印图书信息的方法
print('当前书的信息如下:')
print('书名:{}'.format(self.title))
print('定价:{}'.format(self.price))
print('作者:{}'.format(self.author))
print('出版社:{}'.format(self.publisher))
print('出版时间:{}'.format(self.pubdate))
# 实例化对象 Python不需要用new
book1 = Book('C#精典', 22.9, 'Tom', '清华大学出版社', datetime.date(2016, 3, 1))
print(book1.title) # 打印book1的书名和定价
print(book1.price)
book2 = Book('Python入门到放弃') # 后面几个是默认参数,这里只要传第一个位置参数也可以
book2.author = 'Tom' # 对象创建之后 可以修改默认参数
book2.publisher = '清华大学出版社' # 修改默认参数
book2.print_info() # 调用上面自己定义的打印图书方法,打印book2对应的信息
# 一般在控制台上输入一个列表,返回的就是一个列表,输入元组,返回的就是元组
# 如果是range()、字典表的keys()这些返回的就不一样了,这些都是对象在定义的时候设定的
# 我们自己定义的对象一般可以使用 __repr__() 和 __str__() 这两个特殊方法来设置这些
print(book1) # 打印实例后的对象book1 输出:[图书:C#精典 定价:22.9]
print(book2) # 打印实例后的对象book1 输出:[图书:Python入门到放弃 定价:0.0]
面向对象2
实例方法 类方法 静态方法 静态属性
class Book:
# count写在构造函数外面,是跟实例化无关的东西,没有self,不同于书名,价格,作者
# count放在Book类的外面(全局变量)也行,但是就不属于图书的逻辑关系了,没有类的意义了
count = 0 # 静态成员属性 只属于图书类Book的信息,跟实例化后的每一本图书无关
def __init__(self, title, price=0.0, author=''): # 初始化执行 构造函数
self.title = title # 定义成员属性
self.price = price
self.author = author
Book.count += 1 # 每创建一个对象(实例化),count都会自动+1
def __del__(self): # 删除对象执行
Book.count -= 1 # 每删除一个对象 变量count -1
def __repr__(self):
return f'<图书:{self.title} at 0x{id(self)}>'
def __str__(self):
return f'[图书:{self.title},定价:{self.price}]'
def print_info(self):
print(self.title, self.price, self.author) # 定义一个打印图书信息的方法()
@classmethod # 如果不加装饰器的话就是实例方法,所以调用它的时候就要传递一个实例
def cls_method(cls): # cls可以随便取名字,但是约定成俗一般用cls
print('类方法:第一个参数cls长什么样不重要,都是指类本身,调用时将类作为对象隐式地传入方法'
f',可以通过cls.count调用到静态属性count,图书的数量:{cls.count}')
# 类方法可以调用静态属性和静态方法(cls.属性 cls.方法()),不能调用实例属性和实例方法。
# 类方法通过cls()可以调用到实例方法,但是类里面必须没有实例属性,
# 也就是__init__(self)方法里不能有形参,具体参考后面的一个案例:类方法的一种特殊情况
@staticmethod
# 加上这个装饰器就是跟实例有关的静态方法了,可以被类和对象调用
# 类和实例都可以调用它,但是它不可以调用别人,它没有cls、self参数
def static_method():
print(f'静态方法:可以通过Book.count调用到静态属性count,图书的数量:{Book.count},'
'因为静态属性是可以直接用类本身调用的,虽然可以,但是这并不是静态方法自己来调用的'
',失去了面向对象的意义,静态对象没有cls、self参数,是调用不了别人的')
# 静态方法通过类.属性、类.方法()这样就可以像类方法、实例方法一样调用到静态属性和静态方法了
# 还可以通过实例后的对象 来调用实例属性、实例方法 (这样想 类方法也可以通过这种方式调用实例了)
# 这种方式调用实际上是通过类或者对象调用的,跟静态方法、类方法都没关系,一般不会这样操作,无任何意义
# 调用静态属性和实例属性就用实例方法,只需要调用静态属性就用类方法,不调用任何属性就用静态方法
def method():
# 不加装饰器的话就是伪静态方法(普通函数),与实例无关,只可以被类调用
print('没有加装饰器,也没有self、cls,所以只是普通的函数')
if __name__ == '__main__': # 入口,判断如果是在当前脚本文件里执行当前类
book1 = Book('Python', price=29.0, author='tmo') # 图书1实例化对象
book1.print_info() # 调用打印图书的方法
# 类的静态成员属性
# Book.count += 1
book2 = Book('Flask') # 图书2实例化对象
# Book.count += 1
book3 = Book('Asp.net') # 图书3实例化对象
# Book.count += 1
# 因为上面在类成员里有了Book.count += 1,所以不需要单独每次+1了,实例化一个对象会自动+1
del(book3) # 使用全局函数del()删除一本书(对象)
# 直接这样删除的话图书数量count这个变量不会-1,但是上面定义了删除对象执行就可以了
print('图书的数量:', Book.count)
# 这里打印出来的就是总数了 如果上面的count不是放在上面,而是放在里面 是一个实例属性的话,
# 每次实例化一个对象后就只能book1.count += 1 book2.count += 1 ... 这样按照实例来增加,
# 调用的时候也只能book1.count book2.count ... 这样通过实例来调用,
# 最后打印出来的永远是1,因为他们依附的对象不是一个,每创建一个对象都是独立的
print('图书的数量:', book1.count) # 这样通过实例来调用静态属性也行;尽量不要这样用
book1.count = 99 # 而且还可以修改
print('图书的数量:', Book.count) # 修改后静态属性的没变化
print('图书的数量:', book1.count) # 而通过实例对象调用就是修改后的值了
# 静态成员变量可以通过实例去调用它,只是调用的话,值就是静态属性的值,
# 但是如果调用并把值改了话,那么它就不属于静态属性了,而是属于实例后的对象自己的成员属性了,
# 就像是直接给一个不存在的实例属性赋值,就会创建这个实例属性一样[参考前面说得],
# 跟函数的作用域有点像:函数外的变量和函数里定义的变量同名,如果不指定globa,会是一个新的局部变量
# 类方法
Book.cls_method() # 加上@classmethod装饰器后就可以直接通过类调用了
book2.cls_method() # 加上@classmethod装饰器后依然还可以通过实例调用
# Book.cls_method(book1)
# 类方法如果不加@classmethod装饰器,看起来是个类方法,实际上跟实例方法没区别,
# 所以通过类.方法()调用这个(伪.类)方法的时候必须要传一个实例
# 具体可以参考后面的一个例子:用类调用一个实例方法
# 静态方法
Book.static_method()
book1.static_method()
# 定义的时候不写cls或self
# 加@staticmethod装饰器后,可以通过类和实例调用
# 不加的话是伪静态方法(普通函数),只可以被类调用
类方法的一种特殊情况:使用cls()调用实例
class A(object):
# 属性默认为类属性(可以给直接被类本身调用)
num = "类属性"
# def __init__(self, a):
# self.a = a
# 这里如果有a这样的参数,下面在类方法里就不能用cls().func1()这种方式调用一个实例方法了
# 因为这个a是放在__init__(self)里的,是要实例化并传值的
def __init__(self):
self.b = 123
# 像这样就可以在类方法里用cls().func1()这种方式调用一个实例方法
# 实例方法(必须实例化类之后才能被调用)
def func1(self): # self : 表示实例化类后的地址id
print("func1")
print(self)
# 类方法(不需要实例化类就可以被类本身调用)
@classmethod
def func2(cls): # cls : 表示没有被实例化的类本身
print("func2")
print(cls)
print(cls.num)
cls().func1()
# 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准)
def func3(): # 伪静态方法,普通函数
print("func3")
print(A.num) # 类属性是可以直接用类本身调用的
# A.func1() # 没有实例化无法通过类调用实例方法
# 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
A.func2()
A.func3()
用类调用一个实例方法
class Demo:
def __init__(self, a):
self.a = a
def deme(self, b):
print(self.a, b)
if __name__ == '__main__':
d = Demo('第一个实例对象:')
d.deme('用对象调用')
Demo.deme(d, '用类调用') # 第一个参数要给实例,相当于调self
c = Demo('第二个实例对象:')
c.deme('用对象调用')
Demo.deme(c, '用类调用') # 第一个参数要给实例,相当于调self
print(type(d))
print(type(c))
print(type(Demo))
静态方法、类方法、实例方法区分
复制网上的 加上自己总结
# 定义在类中的代码块叫方法,Python的方法分为『实例方法』、『类方法』、『静态方法』
# 按照从前到后的顺序它们和实例对象的依赖程度依次降低
class Demo:
sfield = '静态属性' # 静态属性(类属性)
def __init__(self, value):
"""初始化方法"""
self.value = value # 实例属性
def ixmethod(self): # self:表示实例化类后的地址id
"""实例方法,测试能否调用实例属性"""
print('ixmethod ->', self.value)
def iymethod(self): # self:表示实例化类后的地址id
"""实例方法,测试能否调用静态属性"""
print('iymethod ->', self.sfield)
def cxmethod1(cls):
"""伪·类方法,测试能否调用实例属性"""
print('cxmethod ->', cls.value)
def cxmethod2(cls):
"""伪·类方法,测试能否调用静态属性"""
print('cxmethod1 ->', cls.sfield)
@classmethod
def cymethod(cls): # cls:表示没有被实例化的类本身
"""真·类方法,测试能否调用静态属性""" # 真.类方法只能调用到静态属性,调用实例属性直接报错函数错误
print('cymethod ->', cls.sfield)
def sxmethod():
"""伪·静态方法,尝试打印一条语句"""
print('伪·静态方法,尝试打印一条语句')
"""
自己没有cls或者self,所以不能像它们那样调用属性,只能打印一条语句了 可怜0.0
直接通过类.属性、对象.属性或类.方法()、对象.方法()、也可以访问到静态属性、实例属性或者其他属性/方法
如果按照这种想法:不管是实例方法、类方法、静态方法都可以直接通过这种方式调用任何想调用的属性/方法,
就不存在能不能调用了,所以为了体现面向对象编程的概念,一般不这样操作,无任何意义
调用静态属性和实例属性就用实例方法,只需要调用静态属性就用类方法,不调用任何属性就用静态方法
所谓的能不能调用是指通过第一个参数cls或self来调用(cls、self叫什么无所谓,一般约定成俗)
"""
@staticmethod
def symethod():
"""真·静态方法,尝试打印一条语句"""
print('真·静态方法,尝试打印一条语句')
d = Demo('实例属性') # 实例化对象,传入实例属性
d.ixmethod() # 实例方法,能调用实例属性:对象.方法()
d.iymethod() # 实例方法,能调用静态属性:对象.方法()
"""实例方法可以调用实例属性也可以调用静态属性(类属性)
但是在调用这个方法的时候只能通过对象.方法()来调用这个方法
因为实例方法只能被实例来调用,这个跟能不能访问属性无关,是实例方法的特性
"""
# Demo.ixmethod() # 实例方法,不能调用实例属性:类.方法()
# Demo.iymethod() # 实例方法,不能调用静态属性:类.方法()
# 会报错,这跟ixmethod()、iymethod()调用什么属性、方法无关,
# 类本来就不能调用实例,非要调用的话,传入一个实例即可:Demo.ixmethod(d)
d.cxmethod1() # 伪·类方法,能调用实例属性:对象.方法()
d.cxmethod2() # 伪·类方法,能调用静态属性:对象.方法()
# Demo.cxmethod1() # 伪·类方法,不能调用实例属性:类.方法()
# Demo.cxmethod2() # 伪·类方法,不能调用静态属性:类.方法()
"""伪.类方法跟实例方法一样
这也说明了类方法的cls只是一个名字,不加@装饰器跟实例方法没什么区别
"""
d.cymethod() # 真·类方法,能调用静态属性:对象.方法()
Demo.cymethod() # 真·类方法,能调用静态属性:类.方法()
"""真.类方法只能调用静态属性(类属性)
类方法调用实例属性直接报错函数错误,因为它的存在就是为了要跟实例分开的,所以类方法不能调用实例属性
类方法可以被类调用(因为类方法里面没有调用实例属性,所以不需要实例化类就可以被类本身调用),
也可以被对象调用(因为没加装饰器之前就是实例方法,加了装饰器只是为了让它可以被类调用)
"""
# d.sxmethod() # 伪·静态方法,尝试打印一条语句:对象.方法()
Demo.sxmethod() # 伪·静态方法,尝试打印一条语句:类.方法()
""""静态方法不可以调用任何属性(没有第一个参数self或cls)
伪.静态方法可以被类调用(因为静态方法里面没有调用实例属性,所以不需要实例化类就可以被类本身调用)
伪.静态方法就相当于是一个普通函数
"""
d.symethod() # 真·静态方法,尝试打印一条语句:对象.方法()
Demo.symethod() # 真·静态方法,尝试打印一条语句:类.方法()
""""静态方法不可以调用任何属性(没有第一个参数self或cls)
真.静态方法可以被类调用(因为静态方法里面没有调用实例属性,所以不需要实例化类就可以被类本身调用),
也可以被对象调用(因为加了装饰器,就等于跟实例关联上了,不加装饰器就是伪.静态方法,只可以被类调用)
"""
结论如下:
1)类方法和静态方法必须要在方法头部加上@开始的修饰符,否则不能视为完全的类方法或静态方法
- 特别是类方法,如果没有加@开始的修饰符,效果和实例方法等价,因为self不是关键字,如果仅仅写下cls编译器并不能识别
2)按照实例方法、类方法、静态方法的顺序,它们对该类的依赖性逐渐降低:
- 实例方法既可以方法实例属性,也可以方法静态属性(通过self.属性来调用)
- 类方法只能调用静态属性(通过cls.属性来调用),如果调用实例属性,直接报错函数错误
- 而静态方法因为没有参数绑定到该类所以仅仅提供函数功能,不能调用实例属性或静态属性,加了@装饰器的真.静态方法就等于把它跟实例关联上了(虽然我没有cls和self不能调用别人,但是现在谁都可以调用我),伪.静态方法因为没有@装饰器,只能通过类调用这个伪静态方法
3)类的实例对象在调用类中定义的方法时,会把自身作为第一个参数传进去(self cls)
这也是为什么不写@classmethod的伪·类方法实际上还是实例方法的本质原因
类方法:第一个参数必须要默认传类,一般习惯用cls
实例方法:第一个参数必须要默认传实例对象,一般习惯用self
静态方法则没有要求
捋一捋:
这个例子的目的是告诉我们哪种方法能调用静态属性/方法,哪种方法能调用实例属性/方法
哪种方法能用类调用、哪种方法能用实例后的对象调用
调用:函数内通过self、cls来调用一些属性/方法(一般调用属性)
被调用:通过类或对象来调用这些方法
对象能调用实例方法、类方法(cls)、真.静态方法(因为加了装饰器,不加的话就是个普通函数,只能被类调用)
类能调用真.类方法(因为加了装饰器,跟类相关联了,加了装饰器就不能用过cls调用实例属性了,所以类可以调用)、静态方法(因为没有cls self,函数里面没有调用任何参数,所以类可以调用)
@property装饰器,把方法改变成属性
import math # 数学模块
class Circle:
def __init__(self, radius):
self.radius = radius
def get_area(self): # 行为 方法()
return math.pi * self.radius ** 2
@property # 加@property 就可以像属性那样调用了
def area(self):
return math.pi * self.radius ** 2
c = Circle(4.0)
print('圆的面积是:{}'.format(c.get_area()))
print('圆的面积是:{}'.format(c.area))
@property装饰器 使用场景
import datetime # 操作时间的模块
class Student:
def __init__(self, name, birthdate):
self.name = name
# self.age = age # 从习惯是来说传入年龄更合适,
self.birthdate = birthdate # 但是从逻辑上来说出生日期更合适
def get_age(self):
return datetime.date.today().year - self.birthdate.year # 今天减去出生日期
# 把方法转换成了属性,同时又有了其他功能。装饰器的作用就可以在不改函数里的代码的同时强化代码
@property # 加装饰器后,调用的时候就不用对象.get_age()这样了,更简洁
def age(self):
return datetime.date.today().year - self.birthdate.year # 今天减去出生日期
@age.setter # @函数名.setter 设置器 @property装饰器里的方法
def age(self, value): # value参数 是用户传的值(形参)
raise ArithmeticError('禁止赋值年龄') # 抛出禁止赋值年龄异常
@age.deleter # @函数名.deleter 删除器 @property装饰器里的方法
def age(self): # 因为是删除 所有没有参数
raise ArithmeticError('禁止删除年龄') # 抛出禁止删除年龄异常
if __name__ == '__main__':
s = Student('Tom', datetime.date(1995, 5, 4))
print(s.birthdate)
# print(s.get_age())
print(s.age) # 属性的方式调用,不用s.get_age()这样调用了,更简洁,都可以输出年龄
'''禁止赋值年龄'''
s.birthdate = datetime.date(1982, 8, 6)
print(s.birthdate) # 这里生日是可以重新赋值的
# s.age = 20
# print(s.age) # 但是由于上面的设置,年龄不可以赋值的,会抛出上面设置好的异常
# 目的就是让别人不可以填写age
# 如果没有上面的装饰器,即使构造函数__init__()里面没有age属性
# 通过s.age=20这种方式依然可以添加age属性
'''禁止删除年龄'''
# del(s.name)
# print(s.name) # 姓名是可以删除的 删除后会抛出异常说对象没有name这个属性
del(s.age)
print(s.age) # 同样由于上面的装饰器设置 年龄是不可以删除的 抛出定义的异常
面向对象:封装 继承 多态
类是为了描述对象而存在的[模板]
封装 继承 多态综合例子1
"""
多态:属于同一类型的不同实例,对同一消息做出不同响应
"""
import datetime
class Department:
# 单独给部门再写个类,丰富部门属性,这个时候部门就不是简单的一个成员属性了
def __init__(self, department, phone, manager):
self.department = department # 部门名称
self.phone = phone # 部门电话
self.manager = manager # 部门经理
def __repr__(self):
return f'<部门:{self.department}>'
# 员工类和部门类属于包含的关系
# : Department只是为了说明这个属性传参的时候接收Department这个类型的,只是为了便于查看代码,
# 实际上department这个属性在实例化的时候还是什么都可以传入,因为Python是动态类型的,
# 并不是说加了之后就只能传入自己定义的Department这个类型的值了,所以不加也一样。
class Employee: # 基类 Employee 员工类
def __init__(self, name, department: Department, birthdate, salary):
self.name = name
self.department = department
self.birthdate = birthdate
self.salary = salary
def __repr__(self):
return f'<员工:{self.name}>'
@property # 员工类的属性,计算年龄(age)
def age(self):
return datetime.date.today().year - self.birthdate.year
def give_raise(self, percent, bonus=.0): # 员工类的的方法,提成和奖金,按基本工资百分比加
self.salary = self.salary * (1 + percent + bonus)
def working(self): # 员工类的的方法,正在做某件事
print('员工:{},正在工作...'.format(self.name))
class Programer(Employee): # 派生类 子类 程序员类,继承员工类
def __init__(self, name, department, birthdate, salary, specialty, project):
self.specialty = specialty # 程序员类自己的属性
self.project = project # 程序员类自己的属性
super().__init__(name, department, birthdate, salary)
"""
继承基类的属性,把基类的方法调用过来就相当于初始化了
这种继承方法不好,因为没有明确指定调用的是哪个基类的属性,在多继承的时候含糊不清
super(Programer, self).__init__(name, department, birthdate, salary)
这里super()括号里可以接收两个参数,子类和self,参数只是说明当前是哪个子类在调用,
在定义的方法里可以使用这种方式访问到基类的方法,
在多态的时候,子类和基类的方法名一样,优先执行的是子类的方法,
但是通过这种方式可以让它执行基类的,如:super(HR, self).working(),
所以super不只是用于构造函数,还可以用于其他骚操作。
"""
def working(self): # 程序员类的的方法,正在做某件事
# 程序员类的方法working()跟员工类的working()重写-重载:多态的概念
print('程序员{}正在{}...'.format(self.name, self.project))
class HR(Employee): # 派生类 子类 HR类,继承员工类
def __init__(self, name, department, birtdate, salary, project, qualification_level=1):
self.project = project # HR类自己的属性
self.qualification_level = qualification_level # HR类自己的属性
Employee.__init__(self, name, department, birtdate, salary)
# 这种继承方法比上面的好,直接明确的写明类型Employee,
# 多继承的时候就不会含糊不清。多继承:HR(Employee, Abbbc):
def working(self): # 重写working方法
print('人事{}正在{}...'.format(self.name, self.project))
super(HR, self).working()
if __name__ == '__main__':
'''程序员类'''
p = Programer('Peter','技术部',datetime.date(1990,5,6),8000,'Flask','摸鱼')
print(p)
print('年龄:',p.age)
print('部门:',p.department)
print('底薪:',p.salary)
p.give_raise(.2, .1) # 给他加提成
print('加提成后薪资:',p.salary)
p.working()
'''HR类'''
hr = HR('铁锤','人事部',datetime.date(1994,5,4),4000,'看书',qualification_level=3)
print(hr)
print('年龄:',hr.age)
print('部门:',hr.department)
print('底薪:',hr.salary)
hr.give_raise(.1)
print('加提成后薪资:',hr.salary)
hr.working()
'''
创建单独的部门类后
'''
dep = Department('技术部', '101-110120152', '张小三') # 构造一个部门对象
p = Programer('Peter', dep, datetime.date(1990, 5, 8), 8000, 'Python-Flask', 'XMall')
print('底薪:', p.salary)
p.give_raise(.2, .1)
print('加提成奖金后薪资:', p.salary)
print(p.department)
# 这里相当于是 print(dep) 输出:<部门:技术部> ,这个是上面定义的__repr__()
# 没定义之前是<__main__.Department object at 0x005DDD30>
print('部门名称:', p.department.department)
print('部门电话:', p.department.phone)
print('部门经理:', p.department.manager)
# 因为部门传入的是dep这个实例,所以调用的时候就调用p.department下的department、phone、manager等...
'''
把人事铁锤当做人事部经理
'''
hr = HR('铁锤', dep, datetime.date(1994, 5, 4), 4000, '看书', qualification_level=3)
hr.department.department = '人事部'
hr.department.phone = '010-1111111111111'
hr.department.manager = hr.name
print('部门名称:', hr.department.department)
print('部门电话:', hr.department.phone)
print('部门经理:', hr.department.manager)
print(hr.__dict__) # 查看对象里的成员和方法
封装 继承 多态综合例子2
import datetime
class Xue_xiao(): # 基类:学校类
def __init__(self, xing_ming, xing_bie, chu_sheng):
self.xing_ming = xing_ming
self.xing_bie = xing_bie
self.chu_sheng = chu_sheng
@property
def nian_ling(self):
return datetime.date.today().year - self.chu_sheng.year
def zoumoujianshi(self, shi_qing): # 学校类的方法:做某件事
print(f'{self.xing_ming}正在{shi_qing}')
class Xue_sheng(Xue_xiao): # 派生类:学生类,继承自学校类
def __init__(self, xing_ming, xing_bie, chu_sheng, ban_ji="", ban_zhu_ren="", sf_ban_gan_bu=False, te_chang=None):
self.ban_ji = ban_ji
self.ban_zhu_ren = ban_zhu_ren
self.sf_ban_gan_bu = sf_ban_gan_bu
self.te_chang = te_chang
super().__init__(xing_ming, xing_bie, chu_sheng)
def zoumoujianshi(self, shi_qing): # 学生类的方法:做某件事
print(f'学生{self.xing_ming}的特长是{self.te_chang},但是他现在他正在{shi_qing}')
def fw_ban_gan_bu(self): # 学生类的方法:封为班干部
self.sf_ban_gan_bu = True
class Lao_shi(Xue_xiao): # 派生类:老师类,继承自学校类
def __init__(self, xing_ming, xing_bie, chu_sheng, jiao_sm=[], sf_ban_zhu_ren=False):
self.jiao_sm = jiao_sm
self.sf_ban_zhu_ren = sf_ban_zhu_ren
super().__init__(xing_ming, xing_bie, chu_sheng)
def fw_ban_zhu_ren(self): # 老师类的方法:封为班主任
self.sf_ban_zhu_ren = True
if __name__ == '__main__':
'''学校类'''
xuexiao = Xue_xiao('李大大', '男', datetime.date(1992, 5, 12))
print(xuexiao.xing_ming, xuexiao.xing_bie, xuexiao.nian_ling)
xuexiao.zoumoujianshi('上厕所')
'''学生类'''
xuesheng =Xue_sheng('二狗子', '男', datetime.date(1995, 3, 25), '92班', '王老师', te_chang='打游戏')
print(xuesheng.xing_ming, xuesheng.xing_bie, xuesheng.nian_ling,
xuesheng.ban_ji, xuesheng.ban_zhu_ren, xuesheng.te_chang)
print(xuesheng.xing_ming + '是不是班干部:', xuesheng.sf_ban_gan_bu)
xuesheng.fw_ban_gan_bu()
print(xuesheng.xing_ming + '是不是班干部:', xuesheng.sf_ban_gan_bu)
xuesheng.zoumoujianshi('看书')
'''老师类'''
laoshi = Lao_shi('王二妞', '女', datetime.date(1990, 2, 10), ['语文', '政治'])
print(laoshi.xing_ming, laoshi.xing_bie, laoshi.nian_ling, laoshi.jiao_sm)
print(laoshi.xing_ming + '是不是班主任:', laoshi.sf_ban_zhu_ren)
laoshi.fw_ban_zhu_ren()
print(laoshi.xing_ming + '是不是班主任:', laoshi.sf_ban_zhu_ren)
laoshi.zoumoujianshi('跟校长谈话')
'''王二妞是学生二狗子的班主任'''
xuesheng.ban_zhu_ren = laoshi
print(xuesheng.ban_zhu_ren.xing_ming)
Python classmethod 修饰符
Python staticmethod() 函数
Python 中的 classmethod 和 staticmethod 有什么具体用途?
python中@classmethod @staticmethod区别
面对对象之@classmethod、@staticmethod用法
Python的类实例方法,类方法,类静态方法
python中的实例方法、静态方法、类方法、类变量和实例变量