class Duck(object):
def fly(self):
print('鸭子飞起来了!')
class Swan(object):
def fly(self):
print('天鹅在空中飞翔!')
class Plane(object):
def fly(self):
print('飞机在空中滑翔!')
# 创建一个函数来调用方法对象
def fly(obj):
obj.fly()
# 通过函数传递参数的方式将对象传入函数
duck = Duck()
fly(duck)
swan = Swan()
fly(swan)
plane = Plane()
fly(plane)
打印输出结果:
/Volumes/苹果微软公共盘/PycharmProjects/venv/bin/python /Volumes/苹果微软公共盘/PycharmProjects/基础班第11期/day-14/上课代码练习/01-多态.py
鸭子飞起来了!
天鹅在空中飞翔!
飞机在空中滑翔!
Process finished with exit code 0
注:一个对象fly的多种表现形式。
class A(object):
# 类属性 直接定义在类中的属性(变量)
# 类属性可以通过实例对象和类对象来访问
# 类属性只能通过类对象来修改,不能通过实例对象来修改
count = 0
def __init__(self):
self.name = '刘亦菲'
# 实例方法
# 在类中定义 以self 为第一个参数的方法,都是实例方法
def run(self):
print('小偷快跑')
# 类方法
@classmethod
def test(cls):
print('测试方法')
# 静态方法
# 不需要指定任何的默认参数,静态方法可以被类对象和实例对象调用(静态方法与类本身无关,就是一个功能函数)
@staticmethod
def static():
print('这是静态方法')
a = A()
# 实例属性 只能由实例对象来访问
a.count = 10 # 相当于重新在实例对象中添加一个新的属性
print(a.count)
print(A.count)
打印输出结果:
E:\python\python.exe D:/PycharmProjects/基础班第11期/day-14/上课代码/属性和方法.py
10
0
Process finished with exit code 0
总结:类属性可以通过类对象来修改(添加),但是不会对类属性本身造成更改。如果通过实例对象来修改,就会报错。报错原因是实例属性并没有该属性名。
class A(object):
# 类属性 直接定义在类中的属性(变量)
# 类属性可以通过实例对象和类对象来访问
# 类属性只能通过类对象来修改,不能通过实例对象来修改
count = 0
def __init__(self):
self.name = '刘亦菲'
# 实例方法
# 在类中定义 以self 为第一个参数的方法,都是实例方法
def run(self):
print('小偷快跑')
# 类方法 (classmethod来修饰类方法)
@classmethod
def test(cls):
print('测试方法')
# 静态方法
# 不需要指定任何的默认参数,静态方法可以被类对象和实例对象调用(静态方法与类本身无关,就是一个功能函数)
@staticmethod
def static():
print('这是静态方法')
a = A()
# 实例属性 只能由实例对象来访问
a.count = 10 # 相当于重新在实例对象中添加一个新的属性
print(a.count)
print(A.count)
# print(A.count)
# print(a.name)
# print(A.name)
# 实例方法的调用
a.run()
A.run(a)
# 实例可以访问类属性和类方法
# 实例属性只能由实例来访问,实例方法实例对象可以直接访问,类对象访问需要添加实例对象作为参数
A.test()
a.test()
A.static()
a.static()
打印输出结果:
E:\python\python.exe D:/PycharmProjects/基础班第11期/day-14/上课代码/属性和方法.py
10
0
小偷快跑
小偷快跑
测试方法
测试方法
这是静态方法
这是静态方法
Process finished with exit code 0
自我总结:
1、实例方法
2、类方法
'''
如下场景:
假设我有一个学生类和一个班级类,想要实现的功能为:
执行班级人数增加的操作、获得班级的总人数;
学生类继承自班级类,每实例化一个学生,班级人数都能增加;
最后,我想定义一些学生,获得班级中的总人数。
'''
# 推导:这个问题用类方法做比较合适,为什么?因为我实例化的是学生,但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的。同时,如果想要获得班级总人数,如果生成一个班级的实例也是没有必要的。
class ClassTest(object):
__num = 0
@classmethod
def addNum(cls):
cls.__num += 1
@classmethod
def getNum(cls):
return cls.__num
# 这里我用到魔术函数__new__,主要是为了在创建实例的时候调用人数累加的函数。
def __new__(self):
ClassTest.addNum()
return super(ClassTest, self).__new__(self)
class Student(ClassTest):
def __init__(self):
self.name = ''
a = Student()
b = Student()
print(ClassTest.getNum())
# 譬如,我想定义一个关于时间操作的类,其中有一个获取当前时间的函数。
import time
class TimeTest(object):
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime())
print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)
理解:如上,使用了静态方法(函数),然而方法体中并没使用(也不能使用)类或实例的属性(或方法)。若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。
其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。
* __new__魔法方法用于创建于返回一个对象。在类准备将自身实例化时调用。
注:在__new__魔法方法于__init__魔法方法共同在一个类中使用时,优先输出的是__new__魔法方法,后输出__init__魔法方法。
演示实例:
class Duck(object):
def __init__(self):
print('这是init魔法方法!')
def __new__(cls, *args, **kwargs):
print('这是snew魔法方法!')
duck = Duck()
打印输出结果:
E:\python\python.exe D:/PycharmProjects/基础班第11期/day-14/上课代码练习/联系一.py
这是new魔法方法!
Process finished with exit code 0
__new__()
方法创建对象__init__
方法'''
在自定义类中实现创建对象
'''
# 思路:
# 1、重写父类(object)的__new__()方法
# 2、并且在该方法内部,调用父类的__new__()方法
class Duck(object):
# init方法是对属性的初始化
def __init__(self):
print('这是init方法!')
# new方法是创建实例对象使用的
def __new__(cls, *args, **kwargs):
print('这是new方法!')
return super().__new__(cls)
duck = Duck()
打印输出结果:
E:\python\python.exe D:/PycharmProjects/基础班第11期/day-14/上课代码练习/联系一.py
这是new方法!
这是init方法!
Process finished with exit code 0
__init__()
方法。__init__()
方法当中的self,实际上就是__new__
返回的实例,也就是对象。__init__()
与__new__()
区别
__init__()
是实例方法,__new__()
是静态方法__init__
在对象创建后自动调用,__new__
是创建对象的方法。__init__
方法与__new__
方法是配合使用的。class Single(object):
obj = None
def __new__(cls, *args, **kwargs):
if cls.obj is None:
# 对创建的obj进行修改
cls.obj = super().__new__(cls)
return cls.obj
else:
return cls.obj
s = Single()
s1 = Single()
print(id(s))
print(id(s1))
打印输出结果:
/Volumes/苹果微软公共盘/PycharmProjects/venv/bin/python /Volumes/苹果微软公共盘/PycharmProjects/基础班第11期/day-14/上课代码/单例模式.py
140712910705088
140712910705088
Process finished with exit code 0
主模块:
from test import *
test()
a = A()
print(a.name)
需调用模块:
print('这是我的第一个模块!')
# a = 1
# b = 10
# print(__name__)
# print(locals())
def test():
print('test')
class A(object):
def __init__(self):
self.name = '刘亦菲'
# a = A()
# print(a.name)
# if __name__ == '__main__': ---函数是程序入口,只有当是本文件运行才能将程序运行成功。
if __name__ == '__main__':
a = A()
print(a.name)
打印主模块输出效果:
/Volumes/苹果微软公共盘/PycharmProjects/venv/bin/python /Volumes/苹果微软公共盘/PycharmProjects/基础班第11期/day-14/上课代码练习/模块/主模块.py
这是我的第一个模块!
test
刘亦菲
Process finished with exit code 0
注:此电脑macOS Big Sur。
注:as是将调用模块中的变量更换名字的词。