很久以前写的了,可能会有不准确的地方

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() #Baz 类中方法
obj.func2() #继承自Bar类
obj.func3() #继承自Foo类

关于继承作用的简单阐释:

如下例,

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) # 18
print(self.name) # zhangsan


obj = Foo('zhangsan')
obj.func()
# 外部调用
print(obj.name) # zhangsan
print(obj.__age) # AttributeError: 'Foo' object has no attribute '__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) # 'China'
print(Foo.__area) # 'Beijing'


obj = Foo()
obj.func()
# 外部调用
print(obj.country) # China
print(obj.__area) # AttributeError: 'Foo' object has no attribute '__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) # beijing
print(self.country) # china
print(self.__area) # AttributeError: 'Foo' object has no attribute '_Foo__area'
print(self.__country) # AttributeError: 'Foo' object has no attribute '_Foo__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") # 静态方法参数::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() # 类方法:: <class '__main__.Foo'>

总结: 方法需要调用对象时使用实例方法

方法需要调用时使用类方法

不需要调用时使用静态方法

类方法与静态方法无需实例化对象

公有方法与私有方法

私有方法声明:

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') # AttributeError: 'Foo' object has no attribute '__private_method'
obj.public_method('world') # private_method:: world
# 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()) # 1
print(obj.end()) # 0

属性

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) # 1
print(obj.end) # 0

属性声明:

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)