Python面向对象编程 (上)
写在前面
参考视频(推荐1.5倍速食用):https://www.bilibili.com/video/BV1A4411v7b2?p=31&vd_source=1a36db16e3fec3ccbe040303ff015aab 参考博客:https://blog.csdn.net/qq_41872653/article/details/109256914 # Chapter1、面向对象基本概念 ## 1、什么是面向对象编程? 面向对象编程(Object-Oriented Programming,OOP)是一种常用的编程思想,它强调万物皆对象,因此在编程时我们可以将现实世界中的事物抽象成程序中的对象,从而更好实现软件的设计与开发。与传统的基于函数的编程不同,面向对象编程注重于将数据与行为封装在一起,即对象既包含数据状态,还包含可调用的行为方法。
面向对象编程的特点在于,它具有封装、继承和多态三大特性。封装意味着将对象的状态和行为进行封装,使其对外只暴露必要的接口,从而提高了安全性和可维护性;继承指的是某个对象可以继承另一个对象的特性,从而快速构建具有相似属性的对象;多态是指同一种行为在不同的对象上具有不同的表现形式,即在不同的情境下,同一个方法可以被不同的对象进行调用。
总之,面向对象编程是一种强大的编程方式,它具有高度封装性、灵活的继承性和强大的多态性,通过使用对象作为程序的基本处理单元,实现了数据和行为的有机结合,可以使程序更加高效、结构清晰,并方便管理和扩展。 ## 2、对象和类的关系 对象可以抽象出某个具体的类,类可以实例化成某个具体的对象。
Chapter2、类的基本语法
1 | class Dog: |
1、类的命名要求首字母大写。
1 | class Money: |
属性相关
2、属性相关概念
变量是可以改变的量值;属性是“属于某个对象的特性”。变量根据访问位置的不同,分为全局变量和局部变量;属性只能通过对象来访问,所以必须先找到对象————而对象又通过变量名来访问,故也遵循访问权限。
### 3、属性添加 1
2
3
4
5class Person:
pass
p = Person()#创建对象
p.age = 18#添加属性
print(p.__dic__ )1
2
3
4
5
6class Person:
pass
p = Person()#创建对象
p.age = 18#添加属性
p.age = 123#修改
print(p.__dict__ )1
2print(p.sex)
报错AttributeError:1
2
3
4
5
6
7class Person:
pass
p = Person()
p.age = 18
del p.age
print(p.age)#AttributeError:
先删除属性,再删除引用的变量。1
2
3
4class Money:
pass
Money.count = 1 #Money看做对象,Money增加count属性
print(Money.count)1
2
3
4
5
6
7class Money:
pass
class Test:
pass
one=Money()
one.__class__=Test
最后one只能访问到Test的类属性1
2
3
4
5
6
7class Money:
age=28
count=1
num=666
Money.age=22 #通过类名-属性修改
print(Money.age)1
del Money.age
总结类属性操作
增、删、改类属性都只能通过类。查询可通过对象和类操作。
P20、类属性的内存存储
1)one访问某个属性,实际上访问的是生成的对象里面__dict__字典的值。
1
2
3
4
5
6class Money:
pass
one=Money()
one.__dict__={'age':99}
print(one.age)
>>>991
2
3
4
5class Money:
age=20
Money.__dict__={'sex':'男'}
>>>报错1
2
3
4
5
6
7
8class Money:
age=20
one=Money()
two=Money()##均指向类的age=20,因为自身没有age属性
print(one.age,two.age)
>>>都是201
2
3
4
5
6
7class Person:
__slots__ = ["age"]#限制对象不能添加age属性
pass
p=Person()
p.age=6
>>>报错
方法相关
P25、概念和作用
1.描述一个目标的行为动作
2.和函数非常类似,都封装了一系列动作,都可以被调用之后执行一系列行为动作,最主要的时调用方式
1
2
3
4
5
6
7class Person:
def eat2(self):
print(1)
print(2)
print(3)
p = Person()
p.eat2()1
2
3
4
5
6
7
8
9
10class Person:
def eat2(self):
print('这是一个实例方法',self)
def leifangfa(cls):
print('这是一个类方法',cls)
def jiangtaifanfa():
print('这是一个静态方法')1
2Person.eat2()
>>>TypeError #确少self1
2
3
4
5
6
7
8
9
10
11
12
13
14#标准调用
class Person:
def eat(self,food):
print("在吃饭",food)
p=Person()
p.eat("potato")#只需要传一个参数
----------------------------------
class Person:
def eat(): #报错,因为以为没有要求传self,但p.eat实例调用时硬塞了一个
实例参数self
print('在吃饭')
p.eat()1
2
3
4
5
6
7
8
9
10
11
12
13class Person:
#装饰器的作用:在保证原函数不变的情况下,直接给这个函数增加一些功能
def leifangfa(cls,a):
print("这是一个类方法" , a)
Person.leifangfa(123)
p = person()
p.leifangfa(666)
func = Person.leifangfa
func(111)1
2
3
4
5
6
7
8
9
10
11
12
13class Person:
#装饰器的作用:在保证原函数不变的情况下,直接给这个函数增加一些功能
def jingtai(cls):
print("这是一个类方法")
Person.jingtai()
p = Person()
p.jingtai()
func = Person.jingtai
func()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Person:
age = 0
def shilifangfa(self):
print(self)
print(self.age)
print(self.num)#可访问到对象属性
def leifangfa(cls):
print(cls)
print(cls.age)
print(cls.num) #不能通过类访问实例属性
def jingtaifangfa():
print(Person.age) #可以通过类访问类属性
P = person()
P.num = 101
2
3
4
5
6
7
8
9
10
11
12
13
14num = 1
print(num.__class__) #输出int
%------------------------------------------
s = "abc"
print(s.__class__) #输出str
%------------------------------------------
class Person:
pass
p = Person()
print(p.__class__) #输出Person
%------------------------------------------
print(int.__class__) #输出type
#其实也是num.__class__.__class___
print(type.__class__)#依然输出type1
2
3
4
5
6
7
8
9def run(self):
print(self)
xxx = type("Dog",(),{"count":0,"run":run})
print(xxx)
print(xxx.__dict__)
d.xxx() #不是d.Dog
print(d)
d.run()1
2
3
4
5
6
7
8
9
10
11
12
13
14查找一般是现在自己里面找,没有就去父类,父类没有就往上找模块,模块没有就是type
#1模块级别的指定
__metaclass__ = xxx
#2
class Animal:
pass
#3
class Dog(Animal):
pass
#4
class Dog:
__metaclass__ = xxx
pass1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Person:
"""
关于这个类的描述,类的作用,类的构造函数等等;类属性的描述
Attributes:
count: int 代表人的个数
"""
count = 1
def run(self, disance, step):
"""
这个方法的作用效果
:param distance:blahblah
:param step:blahblah
:return:
"""
print("跑步")
return distance,step
help(Person) #
1 | class Animal: |
P42、私有化属性-受保护的属性
_y:一个下划线 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
26
27
28
29class Animal:
_x = 10
def test(self):
print(Animal._x)
print(self._x)
pass
#--------------------
class Dog(Animal):
def test2(self):
print(Dog._x)
print(self._x)
pass
a = Animal()
a.test() #类的内部访问
d = Dog()
d.test2() #延伸类的访问
print(Animal._x) #模块的其他部分,可以强行访问,有警告
print(Dog._x)
print(a._x)
print(b._x)
import xxx #模块的其他部分访问,不可访问
print(xxx.a)
from xxx import *
print(a)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
26
27
28
29
30
31
32class Animal:
__x = 10
def test(self): #定义一个实例方法
print(Animal.__x)
print(self.__x)
pass
#--------------------
class Dog(Animal):
def test2(self):
print(Dog.__x)
print(self.__x)
pass
a = Animal()
a.test() #类的内部访问,可以访问
d = Dog()
d.test2() #延伸类的访问,不可以访问
print(Animal.__x) # 模块的其他部分,不可访问
print(Dog.__x)
print(a.__x)
print(d.__x)
a = 1
import xxx #模块的其他部分访问,不可访问
print(xxx.a)
from xxx import *
print(a)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class Person:
#作用:当我们创建好一个实例对对象之后,会自动调用这个方法,来初始化这对象
#init是单词初始化initialization的省略形式
def __init__(self)
self.__age = 18
def setAge(self,value):
if isinstance(value,int) and 0<value<200:
self.__age = value
else:
print("您输入的数据有误,请重新输入")
def getAge(self):
return self.__age
p1 = Person()
p1.setAge(20)
p2 = Person()
print(p1.getAge()) #访问age
print(p1.__age) #报错,只能在类内部访问
print(p2.__age)1
2
3
4
5
6
7class Person:
def init(self): #初始化方法,通过方法设置属性
self.__age = 18
def getAge(self): #部分公开,通过方法实现
return self.__age
p1 = person()
print(p1.getAge())1
2
3
4
5
6
7
8
9
10
11## 49-python-面向对象-只读属性-方案一的优化
1. ```python
class Person(object):
def __init__(self):
self.__age = 18
# 主要作用:可以以使用属性的方法来使用这个方法
def age(self): #部分公开,通过方法实现
return self.__age
p1 = person()
print(p1.age())1
2
3
4
5
6class C(object):
def getx(self): return self._x
def setx(self,value): self._x = value
def delx(self): del self._x
x = property(getx, setx, delx)
#此时,x就是一个属性,可以直接调用x的属性来调用方法1
2
3
4class Person:
pass
print(Person.__bases__) #查看父类(基类)
- property函数方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person(object):
def __init__(self):
self.__age = 18
def get_age(self):
ruturn self.__age
def set_age(self, value):
self.__age = value
age = property(get_age, set_age)
p = Person()
print(p.age)
p.age = 30
print(p.age)
print(p.__dict__) #输出只有_person__age: - 装饰器方法 ### P53、property在经典类中的使用 放弃吧,都用新式类叭! ### P54、只读属性-方案二 总之就是,__ age只不过是把他改了个名字,改成_ 类名 __ age,你知道他的新名字的话你当然可以改。
1
2
3
4
5
6
7
8
9
10
11
12
13class Person(object):
def __init__(self):
self.__age = 18
def age(self):
return self.__age
def age(self, value):
delf.__age = value
p = Person()
p.age = 20 #既可以读取也可以设置### P55、常用内置属性1
2
3
4
5
6
7
8
9
10
11
12
13class Person:
#当我们通过实例.属性 = 值,给一个实力增加一个属性,或者修改属性的时候,就会自动调用这个方法,
#在这个方法内部才会正真地把这个属性,以及对应的数据存储到__dict__字典里面
def __settter__(self, key, value):
print(key, value)
#1.判定,key,是否是我们要设置的只读属性
if key = "age" and key in self.__dict__.keys():#只能新增属性,不能修改属性
print("这个属性是只读属性,不能设置数据")
#2.如果不是只读属性,就给他添加到实例里面去
else:
#self.key = value #这样会陷入死循环
self.__dict__[key] = value
- 类属性:
- dict:类属性
- bases:类的所有父类构成元组
- __doc__类的文档字符
- __name__类名
- __module__类定义所在模块
- 实例属性
- dict:类的实例
- class:实例对应的类
1 |
内置方法
内置方法的作用;完成一些特定的功能 ### P57、信息格式化操作-* __ str
__ * 1
2
3
4
5
6
7
8
9
10class Person:
def __init__(self,n,a):
self.age = a
self.name = n
def __str__(self):
return "name is %s , age is %s . "%(self.name,self.age)
p=Person(Ray,18)
print(p)
is Ray, age is 18. name
P58、信息格式化操作-* __ repr __ *
主要面向开发者 1
2
3
4def Person:
def __init__(self):
return"repr"1
2
3
4
5
6
7class Person:
def __call__(self):
print("xxx")
pass
p = Person()
p() #调用__call__函数1
2
3
4
5
6
7
8class PenFactory:
def __init__(self, p_type):
self.p_type = p_type #这个类只有一个属性
def __call__(self, p_color):
print("创建了一个%s类型的画笔,他是%s颜色的"%(self.p_type, p_color))
gangbiF = penFactory("钢笔") #创建一个对象
gangbiF('红色')1
2
3
4
5
6
7
8
9
10
11
12class Person:
def __init__(self):
self.cache = {} #定义cache属性,为一个字典
def __setitem__(self, key, value):
self.cache[key] = value
def __getitem__(self, key):
return self.cache[key]
def __delitem__(self, key):
del self.cache[key]
p = Person()
p['name'] = 'sz' #执行这行代码的时候,会调用第一个方法
print(p['name']) #调用第二个方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person:
def __init__(self):
self.items = [1, 2, 3, 4, 5, 6, 7, 8] #定义了一个items属性
def __setitem__(self, key, value):
if isinstance(key,silce):
self.items[key] = value #注意切片操作只能修改,不能新增
#self.items.[key.start: key.stop: key.step] = value #这样赋值也可以
def __getitem__(self, key):
return(key.items[key]) #这里可能有错
def __delitem__(self, key):
del self[key]
p = Person()
p[0: 4: 2] = ["a","b"]
print(p.items[0: 4: 2])1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Person:
def __init__(self, age, height):
self.age = age
self.height = height
def __eq__(self, other):
return self.age == other.age #指定相等的比较通过哪个属性比较,
def __ne__(self, other):
return self.age != other.age #指定相等的比较通过哪个属性比较,
p1 = Person(18, 180)
p2 = Person(19, 183)
print(p1 == p2)
#类似的还有:
#gt >
#ge >=
#lt <
#le <=
#可以通过调换参数的方式定义比较方法,进而简化代码1
2
3
4
5
6
7
8import functools
#此装饰器会自动补全所需要的方法
class Person
def __lt__(self, other):
pass
def __eq__(self, other):
pass1
2
3
4
5
6
7
8
9class Person():
def __bool__(self): #通过bool值判定实例是True或False
return False #这里也可以是一个返回布尔值的语句
pass
p = Person()
if p:
print("xx")
>>>不打印1
2
3
4
5
6
7
8
9
10class Person:
def __init__(self):
self.age=20
def __bool__(self):
if self.age >= 18:
return True
p = Person()
if p:
print("已成年")1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person:
def __init__(self):
self.result = 1
def __getitem__(self, item):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
return relf.result
pass
p = person()
for i in p: #当执行for循环时,自动进入__getitem__方法,使用这个方法的返回值作为数据
print(i)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person:
def __init__(self):
self.result = 1
def __getitem__(self, item):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
return relf.result
def __iter__(self):
print("hfkjasdf")
p = person()
for i in p: #当执行for循环时,自动进入__geritem__方法,使用这个方法的返回值作为数据
print(i)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Person:
def __init__(self):
self.result = 1
def __getitem__(self, item):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
#return iter([1,2,3,4]) 如果返回是迭代器,则自动进入迭代器的__next__方法
return relf.result
def __iter__(self):
return self
def __next__(self):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
return relf.result
p = person()
for i in p:
print(i)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class Person:
def __init__(self):
self.result = 1
def __getitem__(self, item):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
#return iter([1,2,3,4]) 如果返回是迭代器,则自动进入迭代器的__next__方法
return relf.result
def __next__(self):
self.result += 1
if self.result >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
return relf.result
p = person()
print(next(p)) #直接进入__next__方法
print(next(p))
print(next(p))
print(next(p))
print(next(p)) #抛出异常,停止遍历1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Person:
def __init__(self):
self.age = 1
def __iter__(self):
self.age = 1 # 如果没有这行命令,那么迭代器只能使用一次
return self
def __next__(self):
self.age += 1
if self.age >=6: #不满足时,跳出循环
raise StopIteration("停止遍历")
return relf.age
p = person()
for i in p:
print(i)
import collection
print(isinstance(p, collection.Iterator))
#返回值为True,表明确实是一个迭代器,需要同时有两个方法__iter__、__next__
next(p) #只要有一个方法__next__就可以访问1
2
3import collection
print(isinstance(p, collection.Iterable))#判定是否为可迭代对象,只要一个方法__iter__就可以 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class Person:
def __init__(self):
self.__age = 10
def age(self):
return self.__age
def age(self, value):
if value < 0:
value = 0
self.__age = value
def age(self):
del self.__age
p = Person()
p.age #注意:这里的age是方法里面的age,不是属性的age
del p.age1
2
3
4
5
6
7
8
9
10
11
12
13
14class Age: #描述器类
def __get__(self, instance, owner):
print("get")
def __set__(self, instance, value):
print("set")
def __delete__(self, instance):
print("delete")
class Person: #主类
age = Age()
p = Person()
p.age = 101
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class Age:
def __get__(self, instance, owner):
print("get")
return self.v
def __set__(self, instance, value):
print("set")
self.v = value
def __delete__(self, instance):
print("delete")
class Person:
age = Age()
p = Person()
p.age = 10
print(p.age)
>>>set
get
10
--------------------------------------------------
p2 = Person()
p2.age = 11
print(p2.age)
>>>11
这时候如果再打印p的话
>>>11
因为都是储存在age里,也就是Age只有一个对象self,即age1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16如果绑定在instance上的话:
class Age:
def __get__(self, instance, owner):
print("get")
return instance.v
def __set__(self, instance, value):
print("set")
instance.v = value
def __delete__(self, instance):
print("delete")
class Person:
age = Age()
就可以分别打印,分别存储
注意层级,def
fashuoshuo()是函数并不是方法,fashuoshuo接收了check,所他自己就是check实例了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def check(func):
def inner():
print("登录成功")
func()
return inner
def fashuoshuo():
print("发说说")
fashuoshuo()
>>>
"登录成功"
"发说说"