很久以前写的了,可能会有不准确的地方
bilibili:
https://www.bilibili.com/video/BV18E411V7ku?p=1&vd_source=7b22d3d988c13bb267c33aa213f757f3
函数式编程与面向对象
eg1:将函数式程序改为对象式程序(封装)
基于函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def msg(num, text): pass
def wechat(num, text): pass
def email(num, text): pass
if __name__ == '__main__': msg(1, "hello") wechat(1, "hello") email(1, "hello")
|
基于对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Message: def msg(self, num, text): pass
def wechat(self, num, text): pass
def email(self, num, text): pass
if __name__ == '__main__': obj = Message() obj.msg(1, "hello") obj.wechat(1, "hello") obj.email(1, "hello")
|
面向对象基本格式
定义
1 2 3
| class 类名: def 方法名(self, var): pass
|
调用
1 2
| obj = 类名() "实例化对象" obj.方法名(var) "通过对象调用方法"
|
eg2:将函数式程序改为对象式程序(传参)
基于函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| def func1(par1, par2, par3): text = '%s,%s,%s' % (par1, par2, par3) print(text)
def func2(par1, par2, par3): text = '%s.%s.%s' % (par1, par2, par3) print(text)
def func3(par1, par2, par3): text = '%s-%s-%s' % (par1, par2, par3) print(text)
if __name__ == '__main__': func1(000, 111, 222) func2(000, 111, 222) func3(000, 111, 222)
|
基于对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class ClassName: def __init__(self, par1, par2, par3): self.p1 = par1 self.p2 = par2 self.p3 = par3
def func1(self): text = '%s,%s,%s' % (self.p1, self.p2, self.p3) print(text)
def func2(self): text = '%s,%s,%s' % (self.p1, self.p2, self.p3) print(text)
def func3(self): text = '%s,%s,%s' % (self.p1, self.p2, self.p3) print(text)
if __name__ == '__main__': obj = ClassName(000, 111, 222) obj.func1() obj.func2() obj.func3()
|
__init__方法(构造方法)解释
1 2 3 4 5 6 7 8 9 10 11
| class ClassName: def __init__(self, par1): self.p1 = par1 self.p2 = 'bbb' def func1(self): text = '%s,%s' % (self.p1, self.p2) print(text)
obj = ClassName('aaa')
|
外部(调用)在实例化对象时通过__init__方法向self容器内传参【将数据封装到对象】,调用其他方法时只需传入self而不用传入全部参数
__init__方法在实例化对象时自动执行
在上例中:
暂时无法在飞书文档外展示此内容
方法内调用方法
1 2 3 4 5 6 7 8 9 10 11 12
| class Foo: def func2(self): print('func2')
def func1(self): self.func2() print('func1')
if __name__ == '__main__': obj = Foo() obj.func1()
|
什么时候使用面向对象,如何使用面向对象
1.归类、提取公共值
1 2 3 4 5 6 7 8 9 10 11 12
| def file_read(file_path): pass def file_write(file_path): pass def file_delete(file_path): pass def dict_read(file_path): pass def dict_write(file_path): pass def dict_delete(file_path): pass
|
以OOP编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class FileOP: def __init__(self, filepath): self.filepath = filepath
def file_read(self): pass def file_write(self): pass def file_delete(self): pass
class DictOP: def __init__(self, filepath): self.filepath = filepath
def dict_read(self): pass def dict_write(self): pass def dict_delete(self): pass
|
2.在类内编写相关所有方法
封装、继承、多态
封装
将相关功能封装到一个类中
1 2 3 4 5 6 7
| class Message: def msg(self, num, text): pass def wechat(self, num, text): pass def email(self, num, text): pass
|
将数据封装到对象中
1 2 3 4 5
| class Person: def init (self, name, age, gender): self. name = name self. age = age self. gender = gender
|
继承
基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Foo: def func1(self): print("func1")
class Bar(Foo): def func2(self): print("func2")
class Baz(Bar): def func3(self): print("func3")
obj = Baz() obj.func1() obj.func2() obj.func3()
|
关于继承作用的简单阐释:
如下例,
1 2 3 4 5 6 7 8 9 10 11 12
| class Foo: def f1(self): pass def f2(self): pass
class Bar: def f1(self): pass def f3(self): pass
|
当Foo、Bar中f1方法相同时可提取父类Base:
1 2 3 4 5 6 7 8 9 10 11
| class Base: def f1(self): pass class Foo(Base): def f2(self): pass
class Bar(Base): def f3(self): pass
|
多继承
多继承相同方法时优先继承靠前面的类(下例中Base1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Base1: def f1(self): print("Base1.f1")
class Base2: def f1(self): print("Base2.f1")
class Foo(Base1, Base2): pass
obj = Foo() obj.f1()
''' output: Base1.f1 '''
|
关于继承中方法的破事
1.明确self是谁(self对应的对象是谁,对象实例的类又是谁)
2.从那个类开始找,没有方法找父类
3.多继承顺序问题
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Base1: def f1(self): print("Base1.f1") def f2(self): print("Base1.f2")
class Base2: def f1(self): print("Base2.f1") def f2(self): print("Base2.f2") def f3(self): print("Base2.f3") self.f1()
class Foo(Base1, Base2): def f0(self): print("Foo.f0") self.f3()
obj = Foo() obj.f0()
|
输出: Foo.f0 Base2.f3 Base1.f1
多态
python原生支持多态,无实际意义
1 2 3 4 5 6 7
| def func(arg): print(arg[0])
func([0, 1, 2]) func((0, 1, 2)) func("012")
|
面向对象成员
变量
实例变量(字段)与类变量(静态字段)
类变量存储于类中,不需要通过实例对象访问,所有实例对象共有
实例变量存储于对象中,通过对象访问,不同对象变量值可以不同
查找时(obj.country)优先查找对象的变量,没有则查找类变量
通过对象对类变量赋值时会创建实例变量(无法通过对象修改类变量)
[Python特性.慎用对象访问类变量]
如果对象中存在相同的变量值考虑提取类变量
1 2 3 4 5 6 7
| class Foo: country = 'China'
def __init__(self, name): self.name = name
|
私有变量与公有变量(成员修饰符)
私有实例变量声明格式self.__变量名
私有类变量声明格式__变量名
私有变量无法在(类)外部调用
实例变量例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Foo: def __init__(self, name): self.__age = 18 self.name = name
def func(self): print(self.__age) print(self.name)
obj = Foo('zhangsan') obj.func()
print(obj.name) print(obj.__age)
|
类变量例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Foo: country = 'China' __area = 'Beijing'
def func(self): print(Foo.country) print(Foo.__area)
obj = Foo() obj.func()
print(obj.country) print(obj.__area)
|
私有变量继承问题
私有变量无法继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Base: __area = 'Beijing' area = 'beijing'
def __init__(self): self.__country = 'China' self.country = 'china'
class Foo(Base): def func(self): print(self.area) print(self.country) print(self.__area) print(self.__country)
obj = Foo() obj.func()
|
方法
实例方法
需要先实例化再调用方法,需要调用对象中封装的值(self)时使用
1 2 3 4 5 6 7 8
| class Foo: def func(self, x): print("实例方法::%s" % x)
obj = Foo() obj.func('hello')
|
静态方法
静态方法声明
1 2 3
| @staticmethod def static_func(): pass
|
静态方法可以无参数(无self参数),可通过类(推荐)或对象调用
对于无需使用对象中封装的变量的方法(不使用__init__传入self的变量)考虑使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Foo: @staticmethod def static_func(): print("静态方法")
@staticmethod def static_func_arg(x): print("静态方法参数::%s" % x)
Foo.static_func()
obj = Foo() obj.static_func_arg("hello")
|
类方法
类方法声明
1 2 3 4
| class Foo: @classmethod def class_func(cls): pass
|
需要使用当前类(不是对象) 的方法使用
1 2 3 4 5 6 7 8 9
| class Foo: @classmethod def class_func(cls): print("类方法::", cls)
Foo.class_func()
|
总结: 方法需要调用对象时使用实例方法
方法需要调用类时使用类方法
不需要调用时使用静态方法
类方法与静态方法无需实例化对象
公有方法与私有方法
私有方法声明:
1 2 3
| class Foo: def __private_method(self): pass
|
私有方法无法外部访问,无法继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Foo: def __private_method(self, arg): print('private_method::', arg) def public_method(self, arg): self.__private_method(arg) print('public_method::', arg)
obj = Foo()
obj.__private_method('hello') obj.public_method('world')
|
属性
eg:将方法转为属性
方法
1 2 3 4 5 6 7 8 9 10 11
| class Foo: def start(self): return 1
def end(self): return 0
obj = Foo() print(obj.start()) print(obj.end())
|
属性
1 2 3 4 5 6 7 8 9 10 11
| class Foo: @property def start(self): return 1 @property def end(self): return 0
obj = Foo() print(obj.start) print(obj.end)
|
属性声明:
1 2 3 4
| class Foo: @property def bar(self): pass
|
属性区别于方法,无法传入其他参数(self除外)。调用时无需加()
直接属性.方法
当无需传参、有返回值时考虑使用
公有属性与私有属性
私有属性声明:
1 2 3 4
| class Foo: @property def __private(self): return 'private'
|
组合/嵌套(建模)
基本使用
相当于在对象内套用对象,调用时多次解构(.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class School: def __init__(self, school_name, school_address): self.name = school_name self.address = school_address
obj = School("shuochang_daizhuan", "shahe")
class Teacher: def __init__(self, teacher_name, teacher_age, teacher_salary): self.name = teacher_name self.age = teacher_age self.__salary = teacher_salary self.school = None
teacher = Teacher("rapper", 18, 1000) teacher.school = obj print(teacher.school.name) print(teacher.school.address) print(teacher.name)
|