python中的类和对象
python类定义
python类的定义
- 使用
class
关键字定义一个类,并且类名的首字母要大写 - 当创建的类型不能用简单类型表示时就需要创建类
- 类把需要的变量和函数组合在一起,即为“封装”
python类的结构
class 类名(遵循大驼峰语法规则->首字母大写):
成员变量
成员函数
实例1:
class Money: # 创建一个类
pass
print(Money) # 类
print(Money.__name__) # 类名
one = Money() # 对象实例化
print(one) # Money的对象
print(one.__class__) # 对象的类
结果输出:
<class '__main__.Money'>
Money
<__main__.Money object at 0x0000020572266FD0>
<class '__main__.Money'>
实例2:
# 1. 定义一个类
class Person:
pass
# 2. 根据类,创建一个对象
p = Person()
# 3. 给p对象,增加一些属性
p.age = 10 # 新增一个属性
p.height = "120"
p.age = 15 # 修改一个属性
p.pets = ['xiaomao', 'xiaogou']
# 4. 验证是否添加成功
print(p.__dict__) # 类属性
print(p.__class__) # 类属性
print(p.age) # 对象属性
print(p.pets, id(p.pets))
# 5. 修改属性
p.pets = [1, 2] # 修改属性
print(p.pets, id(p.pets))
# 6. 访问属性
p.pets.append(3) # 访问属性,id不会
print(p.pets, id(p.pets))
# 7. 删除属性
del p.age
print(p.age)
结果输出:
{'age': 15, 'height': '120', 'pets': ['xiaomao', 'xiaogou']}
<class '__main__.Person'>
15
['xiaomao', 'xiaogou'] 2478101597248
[1, 2] 2478111267584
[1, 2, 3] 2478111267584
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1481, in <module>
print(p.age)
AttributeError: 'Person' object has no attribute 'age'
实例3:# 类属性-增加(方式1)
class Person: # 类也是对象
pass
Person.num = 1 # 增加属性
print(Person.num)
print(Person.__dict__)
结果输出:
1
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'num': 1}
实例4: # 类属性-增加(方式2)
class Person: # 类也是对象
age = 10 # 增加属性
height = 120 # 增加属性
number = 9527 # 增加属性
print(Person.age)
print(Person.height)
print(Person.number)
print(Person.__dict__)
结果输出:
10
120
9527
{'__module__': '__main__', 'age': 10, 'height': 120, 'number': 9527, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
实例5:# 类属性-查询属性
class Person: # 类也是对象
age = 10
height = 120
number = 9527
jack = Person() # 类的实例化
print(jack.__class__)
print(jack.age)
结果输出:
<class '__main__.Person'>
10
对象查询属性的过程:首先先看对象自身有没有属性,如果有直接输出,如果没有,则通过
__class__
访问到类对象,如果有则输出,如果没有则报错
实例6:
class Person: # 类也是对象
age = 10
height = 120
number = 9527
jack = Person() # 类的实例化
jack.sex = 'female'
print(jack.__class__)
print(jack.age)
print(jack.sex)
print(Person.sex)
结果输出:
<class '__main__.Person'>
10
female
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1494, in <module>
print(Person.sex)
AttributeError: type object 'Person' has no attribute 'sex'
类对象不能访问实例化对象的属性
实例7:# 类属性-修改属性
class Person: # 类也是对象
age = 10
height = 120
number = 9527
jack = Person()
jack.age = 12
print(jack.age)
print(Person.age) # 对象改变属性,类对象的属性不变
Person.age = 14
print(jack.age)
print(Person.age) # 修改类属性,则类属性改变
结果输出:
12
10
12
14
类属性修改只能通过类修改,而查询对象属性,首先要在对象里查找,查找不到则会去类对象查找,修改对象属性,则只有对象属性改变,类对象属性不变
实例8:# 类属性-删除属性
class Person: # 类也是对象
age = 10
height = 120
number = 9527
one = Person()
print(one.age)
print(Person.age)
del Person.age # 删除类属性
print(one.age)
print(Person.age)
结果输出:
10
10
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1493, in <module>
print(one.age)
AttributeError: 'Person' object has no attribute 'age' # 类属性删除后不再有age属性
看是否能不能通过对象删除类属性呢?
class Person: # 类也是对象
age = 10
height = 120
number = 9527
one = Person()
print(one.age)
print(Person.age)
del one.age # 删除类属性
print(one.age)
print(Person.age)
结果输出:
10
10
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1492, in <module>
del one.age # 删除类属性
AttributeError: age # 对象本身就没有age属性,因此报AttributeError,与上面案例的报错不同
实例9:# 类属性-更改
class Person: # 类也是对象
age = 10
height = 120
number = 9527
Person.__dict__ = {'sex': 'female'} # 类属性都存在`__dict__`里,看是否可以通过更改`__dict__`来更改类属性
结果输出:
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1489, in <module>
Person.__dict__ = {'sex': 'female'}
AttributeError: attribute '__dict__' of 'type' objects is not writable # 类属性是只读不可写的
class Person: # 类也是对象
age = 10
height = 120
number = 9527
one = Person()
one.__dict__["age"] = 12
print(one.age)
一般情况下,属性存储在
__dict__
字典中,类对象的__dict__
为只读,但是一般对象可以直接修改__dict__
实例10:# 类属性-查询、新增、修改
class Person: # 类也是对象
age = 10
height = 120
number = 9527
jack = Person()
jack.age = jack.age + 5
print(Person.age)
print(jack.age)
结果输出:
10
15
jack.age
首先查看jack
对象里有没有age
,没有,那么去Person
里查询age
,得到age
之后又把age + 5
赋值给jack.age
。因此等号右jack.age
是查询Person
的age
,
等号左jack.age
是对jack
新增age
属性。总结:对jack
而言是新增age
属性,对Person
不变。(新增和修改的判断依据是看原对象里有没有,如果有则是修改,如果没有则是新增)
实例11:# 类属性-限定新增属性
__slots__
实现限定新增属性功能
class Person: # 类也是对象
__slots__ = ['age']
pass
p1 = Person()
p1.age = 10
print(p1)
p1.num = 9527
结果:
<__main__.Person object at 0x000001A37B755FD0>
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1491, in <module>
p1.num = 9527
AttributeError: 'Person' object has no attribute 'num'
__slots__
已经限定了类属性,再增加其他属性则会报错
python面向对象-方法
class Person: # 创建类
def eat(self):
print('eat rice')
p = Person() # 创建对象
p.eat()
结果输出:
eat rice
类方法的作用是实现目标动作
方法的划分
class Person: # 创建类
def eat(self): # 实例方法
print('这是一个实例方法', self)
@classmethod
def leifangfa(cls): # 类方法
print('这是一个类方法', cls)
@staticmethod
def jingtaifangfa(): # 静态方法
print('这是一个静态方法')
p = Person() # 创建对象
print(p)
p.eat()
print('*'*20)
Person.leifangfa()
print('*'*20)
Person.jingtaifangfa()
结果输出:
<__main__.Person object at 0x000001A6ED0C5F70>
这是一个实例方法 <__main__.Person object at 0x000001A6ED0C5F70>
********************
这是一个类方法 <class '__main__.Person'>
********************
这是一个静态方法
实例方法、类方法、静态方法的存储位置在哪?是在类对象里还是在实例对象中呢?
class Person: # 创建类
def eat(self): # 实例方法
print('这是一个实例方法', self)
@classmethod
def leifangfa(cls): # 类方法
print('这是一个类方法', cls)
@staticmethod
def jingtaifangfa(): # 静态方法
print('这是一个静态方法')
p = Person() # 创建对象
print(p.__dict__)
print(Person.__dict__)
结果输出:
{} # 说明不在实例对象里
{'__module__': '__main__', 'eat': <function Person.eat at 0x00000273F5C1C4C0>, 'leifangfa': <classmethod object at 0x000002738F286FD0>, 'jingtaifangfa': <staticmethod object at 0x000002738F286FA0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} # 在类对象里
万物皆对象,int、str、甚至函数也都是对象
class Person: # 创建类
def eat(self): # 实例方法
print('这是一个实例方法', self)
@classmethod
def leifangfa(cls): # 类方法
print('这是一个类方法', cls)
@staticmethod
def jingtaifangfa(): # 静态方法
print('这是一个静态方法')
def run():
print('run')
p = Person() # 创建对象
p.age = 10
print(p.__dict__)
p.age = run
print(p.__dict__)
结果输出:
{'age': 10}
{'age': <function run at 0x000001F545BFF1F0>}
小结:
- 实例方法:默认第一个参数需要接收到一个实例
- 类方法:默认第一个参数需要接收到一个类
- 静态方法:第一个参数啥也不用接收
划分的依据: 方法的第一个参数必须要要接收的数据类型,不管是哪一种类型的方法,都是存储在类当中,没有在实例当中的,不同类型方法的调用方式不同 - 万物皆对象,数字、字符串、函数都是对象,都可以赋给实例对象属性
python面向对象-方法
a) 实例方法
class Person:
def eat(self, food):
print("在吃饭, 吃", self, food)
p = Person()
print(p) # 无需传递第一个参数self, self相当于p
p.eat("米饭")
结果输出:
<__main__.Person object at 0x000001F54FB75FD0>
在吃饭, 吃 <__main__.Person object at 0x000001F54FB75FD0> 米饭
实例1
class Person:
def eat(self, food):
print("在吃饭, 吃", food)
p = Person() # ()代表创建实例
p.eat("大米")
结果输出:
在吃饭, 吃 大米
b) 类方法
class Person:
@classmethod
def leifangfa(cls, a):
print('这是一个类方法', cls, a)
Person.leifangfa(123)
p = Person()
p.leifangfa(666)
func = Person.leifangfa
func(111)
结果输出:
这是一个类方法 <class '__main__.Person'> 123
这是一个类方法 <class '__main__.Person'> 666
这是一个类方法 <class '__main__.Person'> 111
c) 静态方法
Convert a function to be a static method.
A static method does not receive an implicit first argument. To declare a static method
class Person:
@staticmethod
def jingtaifangfa():
print('这是一个静态方法')
Person.jingtaifangfa()
p = Person()
p.jingtaifangfa()
func = Person.jingtaifangfa # 注意这里没有括号
func()
结果输出:
这是一个静态方法
这是一个静态方法
这是一个静态方法
实例1:类属性和实例属性
class Person:
age = 0
p = Person()
p.num = 10
# 类属性
print(Person.age)
print(p.age)
# 实例属性
print(p.num)
结果输出:
0
0
10
实例2:
class Person:
age = 0
def shilifanfga(self):
print(self)
print(self.age)
print(self.num)
# @classmethod
# def leifangfa(cls):
# print(cls)
# print(cls.age)
# print(cls.num)
#
# @staticmethod
# def jingtaifangfa():
# print(Person.age)
# print(Person.num)
p = Person()
p.num = 10
p.shilifanfga()
# p.leifangfa()
# p.jingtaifangfa()
结果输出:
<__main__.Person object at 0x0000029AE7D35FD0>
0
10 # 能访问
说明实例方法能够访问实例对象属性
实例3:
class Person:
age = 0
def shilifanfga(self):
print(self)
print(self.age)
print(self.num)
@classmethod
def leifangfa(cls):
print(cls)
print(cls.age)
print(cls.num)
#
# @staticmethod
# def jingtaifangfa():
# print(Person.age)
# print(Person.num)
p = Person()
p.num = 10
# p.shilifanfga()
p.leifangfa()
# p.jingtaifangfa()
结果输出
<class '__main__.Person'>
0
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1540, in <module>
p.leifangfa()
File "D:\public\python_exam\hello.py", line 1529, in leifangfa
print(cls.num)
AttributeError: type object 'Person' has no attribute 'num'
说明类方法不能访问实例对象属性
实例4:
class Person:
age = 0
def shilifanfga(self):
print(self)
print(self.age)
print(self.num)
@classmethod
def leifangfa(cls):
print(cls)
print(cls.age)
print(cls.num)
#
@staticmethod
def jingtaifangfa():
print(Person.age)
print(Person.num)
p = Person()
p.num = 10
# p.shilifanfga()
# p.leifangfa()
p.jingtaifangfa()
结果输出:
0
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1541, in <module>
p.jingtaifangfa()
File "D:\public\python_exam\hello.py", line 1534, in jingtaifangfa
print(Person.num)
AttributeError: type object 'Person' has no attribute 'num'
静态方法也不能访问实例对象属性
实例5: 万物皆对象
num = 10
print(num.__class__)
s = 'abc'
print(s.__class__)
结果输出:
<class 'int'>
<class 'str'>
实例6: 万物皆对象(类的原始-元类)
num = 10
print(num.__class__)
s = 'abc'
print(s.__class__)
class Person:
pass
p = Person() # 对象实例化
print(p.__class__)
print(int.__class__.__class__)
print(s.__class__.__class__)
结果输出:
<class 'int'>
<class 'str'>
<class '__main__.Person'>
<class 'type'> # 元类
<class 'type'> # 元类
解释:
10
的类对象是int
,int
的类对象是type
(元类),再向上还是type
,已经到头了,同理,abc
的类对象是str
,str
的类对象是type
实例7 元类type的使用
num = 10
print(type(num)) # 第一种用法
def run(self):
print(self, 'run')
x = type('Dog', (), {'count': 0, 'run': run}) # 第二种使用type创建类对象的方法
print(x)
print(x.__dict__)
d = x()
print(d.count)
print(d.run)
结果输出:
<class 'int'>
<class '__main__.Dog'>
{'count': 0, 'run': <function run at 0x0000023ADC7FF1F0>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
0
<bound method run of <__main__.Dog object at 0x0000023AF5F95FD0>>
type
第一种使用方式,直接获取实例对象的类对象,第二种使用方式,创建类对象
python面向对象-类的创建流程
- 步骤1. 检测类对象中是否有明确
__metaclass__
属性 - 步骤2. 检测父类中是否存在
__metaclass__
属性 - 步骤3. 检测模块中是否存在
————metadata__
属性 - 步骤4. 通过内置的
type
元类来创建类对象
python面向对象-类的描述
写注释的目的有1)逻辑清晰;2)利于多人开发;3)方便生成项目文档
class Person:
"""
关于这个类的描述,类的作用,类的构造函数等等;类属性的描述
Attributes:
count: int 代表人的个数
"""
# 表示人的个数
count = 1
def run(self, distance, step):
"""
这个方法的作用效果
:param distance: 参数含义,参数的类型,是否有默认值
:param step:
:return: 返回结果含义,返回数据的类型
"""
print('开始跑!')
return distance/step
help(Person) # 查看注释文档
结果输出:
Help on class Person in module __main__:
class Person(builtins.object)
| 关于这个类的描述,类的作用,类的构造函数等等;类属性的描述
| Attributes:
| count: int 代表人的个数
|
| Methods defined here:
|
| run(self, distance, step)
| 这个方法的作用效果
| :param distance: 参数含义,参数的类型,是否有默认值
| :param step:
| :return: 返回结果含义,返回数据的类型
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| count = 1
生成项目文档- 使用内置模块pydoc
步骤1: 打开cmd
步骤2: 进入python
文件路径
步骤3: 使用python
内置函数 python -m pydoc -p 1234
# 使用内置函数pydoc
打开端口1234
步骤4: 打开浏览器 http://localhost:1234/hello.html
以上步骤就可以看到生成项目文档
将项目文档写入html
里
在文件目录cmd
下执行python -m pydoc -w
文件.py
会自动生成文件.html
,可以通过浏览器打开
python面向对象-私有化属性
a) 公有属性
class Animal:
x = 10 # 公有属性
def test(self):
print(Animal.x) # 类方法可以访问公有属性
print(self.x) # 类方法可以访问公有属性
pass
class Dog(Animal): # 继承Animal
def test2(self):
print(Dog.x) # 衍生类也可以访问公有属性
print(self.x) # 衍生类也可以访问公有属性
pass
# 测试代码
a = Animal()
a.test()
print('*'*20)
d = Dog()
d.test2()
print('*'*20)
print(Animal.x)
print(Dog.x)
print(a.x)
print(d.x)
结果输出:
10
10
********************
10
10
********************
10
10
10
10
模块导入私有化属性
使用方法1:
import 模块
print(模块.func)
使用方法2:
from 模块 import func
print(func)
b) 受保护属性 _属性
#
class Animal:
_x = 10 # 受保护属性
def test(self):
print(Animal._x)
print(self._x)
pass
a = Animal()
a.test()
class Dog(Animal): # 继承Animal
def test2(self):
print(Dog._x) # 衍生类也可以访问公有属性
print(self._x) # 衍生类也可以访问公有属性
pass
d = Dog()
d.test2()
print(Animal._x) # 强行访问没问题,但是不建议这样访问
print(Dog._x) # 强行访问没问题,但是不建议这样访问
print(a._x) # 强行访问没问题,但是不建议这样访问
print(d._x) # 强行访问没问题,但是不建议这样访问
结果输出:
10
10
10
10
10
10
受保护类属性,不管是自己类内部还是衍生类内部都可以访问
受保护变量跨模块访问则出现问题
如果
from 模块 import _func
print(_func) # 不报错
但是
from 模块 import *
print(_func) # 报错,没有_func变量
_属性即受保护属性,类内部访问不报错,子类内部访问不报错,模块内其他位置访问如类访问(包含父类和派生类)会出现警告不报错;实例访问(父类实例和派生类实例)会出现警告不报错,而跨模块访问的时候,
import
形式导入则警告不报错,from module import *
的形式导入,如果有__all__
(all = ["受保护变量属性"])指明对应变量则警告不报错,没有__all__
指明对应变量则报错
c) 受保护属性
实例1
class Animal:
__x = 10 # 受保护属性
def test(self):
print(Animal.__x)
print(self.__x)
pass
a = Animal() # 类里面方法可以访问受保护属性
a.test()
class Dog(Animal): # 继承Animal
def test2(self):
print(Dog.__x)
print(self.__x)
pass
d = Dog()
d.test2()
结果输出:
10
10
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1617, in <module>
d.test2()
File "D:\public\python_exam\hello.py", line 1611, in test2
print(Dog.__x)
AttributeError: type object 'Dog' has no attribute '_Dog__x'
类里面方法可以访问受保护属性,而子类不能访问父类受保护属性
实例2
class Animal:
__x = 10 # 受保护属性
def test(self):
print(Animal.__x)
print(self.__x)
pass
a = Animal()
print(Animal.__x) # 双下划线的受保护属性,类不能被访问,
print(a.__x) # 类实例对象不能访问
class Dog(Animal): # 继承Animal
def test2(self):
print(Dog.__x)
print(self.__x)
pass
d = Dog()
print(Dog.__x) # 双下划线的受保护属性,子类不能被访问
print(d.__x) # 双下划线的受保护属性,子类实例对象不能被访问
结果输出:
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1606, in <module>
print(Animal.__x)
AttributeError: type object 'Animal' has no attribute '__x'
双下划线的受保护属性,在本模块都不能被访问,无论是类还是子类,类实例对象还是子类实例对象均不能访问
实例3 跨模块访问
方式1:
在原模块中
__x = 10
在新模块中
from 原模块 imort *
print(__x) #结果报错
方式2:
在原模块中
__all__ = ["__x"]
__x = 10
在新模块中
from 原模块 imort *
print(__x) #结果不报错
双下划线的受保护属性的跨模块访问,参照单下划线开头变量的访问原则
d) 私有属性的实现机制
主要通过名字重整(Name Mangling),重名__x为另外一个名词,如_类名__x,目的是访问外界直接访问,防止被子类同名称属性覆盖
class Animal:
__x = 10 # 受保护属性
def test(self):
print(Animal.__x)
print(self.__x)
pass
a = Animal()
print(Animal.__dict__)
print(Animal._Animal__x) # 如果想访问x,这样访问
结果输出:
{'__module__': '__main__', '_Animal__x': 10, 'test': <function Animal.test at 0x00000229FB1CC4C0>, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None} # 重点看=='_Animal__x': 10==
10
e) 私有化属性的应用场景
class Person: # 属性最好设计为实例属性而非类属性,不然所有的实例对象属性都相同
# 主要作用,当创建好一个实例对象后,会自动调用这个方法,来初始化这个对象
def __init__(self):
self.__age = 18 # 私有属性
def setAge(self, value):
if isinstance(value, int) and 0 < value < 200: # 私有属性起到数据保护和数据过滤的作用
self.__age = value
else:
print('Error')
def getAge(self):
return self.__age
p1 = Person()
p1.setAge(220) # 设置数值
print(p1.getAge()) # 获得数值
p2 = Person()
p2.setAge(23)
print(p2.getAge())
结果输出:
Error
18
23
注意针对私有化属性 x: 几乎在所有地方都可以访问,_y:代表受保护属性,在类的内部和子类的内部访问,__z:代表私有属性,只能在类内部访问,以上均为权限问题,还有其他的x_或__x__则是规范问题,建议与系统内置做区分
python面向对象-只读属性
- 概念 一个属性(一般指实例属性),只能读取,不能写入
- 应用场景 有些属性,只限在内部根据不同场景进行修改,而对外界来说,不能修改,只能读取
实例1
class Person:
def __init__(self):
self.age = 18 # 这样写既可以访问又可以修改
p1 = Person()
print(p1.age)
p1.age = 10
print(p1.age)
结果输出:
18
10
实例2:
class Person:
def __init__(self):
self.__age = 18 # 这样写只可以访问
p1 = Person()
p1.__age = 100
print(p1.__dict__)
print(p1._Person__age) # 可以这样访问,但不建议
print(p1.__age) # 和类初始化属性不是一个东西
结果输出:
{'_Person__age': 18, '__age': 100}
18
100
实例3
class Person:
def __init__(self):
self.__age = 18 # 这样写只可以访问
def getAge(self): # 提供公开的方法
return self.__age # 访问只读属性操作
p1 = Person()
print(p1.getAge())
结果输出:
18
实例4:
class Person:
def __init__(self):
self.__age = 18 # 这样写只可以访问
# 主要作用,可以使用属性的方式,来使用这个方法
@property
def getAge(self):
return self.__age # 访问只读属性操作
p1 = Person()
print(p1.getAge) # ==这里已经是返回值了==
print(p1.getAge()) # 不能加括号
结果输出:
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1660, in <module>
print(p1.getAge())
TypeError: 'int' object is not callable
18
实例5:
class Person:
def __init__(self):
self.__age = 18 # 这样写只可以访问
# 主要作用,可以使用属性的方式,来使用这个方法
@property # 装饰器property作用限定读取
def age(self):
return self.__age # 访问只读属性操作
p1 = Person()
p1.age = 10 # 已经设定为只读,不能设置
print(p1.age)
结果输出:
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1659, in <module>
p1.age = 10
AttributeError: can't set attribute
实例6
class Person:
def __init__(self):
self.__age = 18 # 这样写只可以访问
# 主要作用,可以使用属性的方式,来使用这个方法
@property
def age(self):
return self.__age # 访问只读属性操作
@age.setter # 对只读属性修改操作
def age(self, value):
self.__age = value
p1 = Person()
p1.age = 10 # 可以对只读属性重新赋值
print(p1.age)
结果输出:
10
python面向对象-新式类和经典类
python 2.x
,如果定义一个类,没有显示的继承自object
,那么这个类是一个经典类, 必须显示继承pbject
,它才是一个新式类
python 3.x
如果直接定义一个类,会隐式继承object
,默认情况下,就已经是一个新式类
class Person:
pass
print(Person.__base__)
结果输出:
<class 'object'>
实例1--property在新式类中的应用
class Person(object):
def __init__(self):
self.__age = 10
def get_age(self):
print('----,get')
return self.__age
def set_age(self, value):
print('----,set')
self.__age = value
age = property(get_age, set_age)
p = Person()
print(p.age)
p.age = 90
print(p.age)
print(p.__dict__)
结果输出:
----,get
10
----,set
----,get
90
{'_Person__age': 90}
实例2:
class Person(object):
def __init__(self):
self.__age = 10
@property
def age(self):
print('-----, get')
return self.__age
@age.setter
def age(self, value):
print('-----, set')
self.__age = value
p = Person()
print(p.age) # 读取私有属性
p1 = Person()
p1.age = 18 # 修改私有属性
print(p1.age)
结果输出:
-----, get
10
-----, set
-----, get
18
实例3:
class Person:
def __init__(self):
self.__age = 10 # 初始化一个私有属性
@property # 装饰器可以使外界访问这个只读属性的方法
def age(self):
return self.__age
p = Person()
print(p.age)
结果输出:
10
实例4:增加修改只读属性
class Person:
# 当我们通过实例,属性=值,给一个实例增加一个属性,或者说,修改一下属性值的时候,都会调用这个方法
# 在这个方法内部,才会真正的把这个属性,以及对于的数据,给存储到__dict__字典里
def __setattr__(self, key, value): # 增加只读属性
print(key, value)
if key == 'age' and key in self.__dict__.keys():
print("这个属性是只读属性,不能设置数据")
else:
self.__dict__[key] = value
p = Person()
p.age = 18
print(p.__dict__)
p.height = 120
print(p.__dict__)
print(p.age)
print(p.height)
p.age = 90
print(p.age)
结果输出:
age 18
{'age': 18}
height 120
{'age': 18, 'height': 120}
18
120
age 90
这个属性是只读属性,不能设置数据
18
python面向对象-常用内置属性
内置特殊属性主要包括类属性和实例属性
类属性主要包括:
- dict: 类属性
- bases : 类的所有父类构成元组
- doc : 类的文档字符串
- name :类名
- module : 类定义一所在的模块
实例属性主要包括: - dict : 实例的属性
- class : 实例对应的类
实例1:
class Person:
"""
这是一个人类
"""
age = 19
def __init__(self):
self.name = "sz"
def run(self):
print("run")
print(Person.__dict__) # 类的属性
print(Person.__bases__) # 类的所有父类构成元组
print(Person.__doc__) # 类的文档字符串
help(Person)
print(Person.__name__) # 类名
print(Person.__module__) # 类定义所在的模块
print('*'*20)
p = Person()
print(p.__class__) # 实例对象的类 <类型 '所在模块名称.所属类名称'>
结果输出:
{'__module__': '__main__', '__doc__': '\n 这是一个人类\n ', 'age': 19, '__init__': <function Person.__init__ at 0x0000018D7B8AC700>, 'run': <function Person.run at 0x0000018D14660550>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
(<class 'object'>,)
这是一个人类
Help on class Person in module __main__:
class Person(builtins.object)
| 这是一个人类
|
| Methods defined here:
|
| __init__(self)
| Initialize self. See help(type(self)) for accurate signature.
|
| run(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| age = 19
Person
__main__
********************
<class '__main__.Person'>
python面向对象-私有方法
class Person:
__age = 18
def __run(self): # 私有方法
print('run')
p = Person()
print(p.__dict__)
print(p.__run())
结果输出:
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1770, in <module>
print(p.__run())
AttributeError: 'Person' object has no attribute '__run'
{}
实例1: 私有方法的调用
class Person:
__age = 18
def __run(self): # 私有方法
print('run')
def _Person__run(self):
print('xxx')
p = Person()
p._Person__run()
print(Person.__dict__)
结果输出:
xxx
{'__module__': '__main__', '_Person__age': 18, '_Person__run': <function Person._Person__run at 0x000002292CE0C700>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
实例2: 内置特殊方法 __str__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self): # 内置特殊方法
return '这个人的姓名是%s, 这个人的年龄是%s' % (self.name, self.age)
p1 = Person('sz', 18)
print(p1.name)
print(p1.age)
print(p1)
p2 = Person('na', 10)
print(p2.name)
print(p2.age)
s = str(p1)
print(s, type(s))
结果输出:
sz
18
这个人的姓名是sz, 这个人的年龄是18
na
10
这个人的姓名是sz, 这个人的年龄是18 <class 'str'>
实例3: 内置特殊方法 __repr__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self): # 内置特殊方法
return '这个人的姓名是%s, 这个人的年龄是%s' % (self.name, self.age)
def __repr__(self): # 内置特殊方法, 重写之后输出返回值,如果没有重写则使用默认方法, 要么面向开发人员,要么面向用户
return "reprxxxx"
p1 = Person('sz', 18)
print(repr(p1))
结果输出:
reprxxxx
实例4: __repr__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self): # 内置特殊方法
return '这个人的姓名是%s, 这个人的年龄是%s' % (self.name, self.age)
p1 = Person('sz', 18)
print(repr(p1)) # repr 显示实例对象的类地址信息
结果输出:
<__main__.Person object at 0x000001D655B46FD0>
实例5: __repr__
# 面向python解释器开发人员
import datetime
t = datetime.datetime.now()
print(t) # 面向用户
tmp = repr(t)
print(repr(t)) # 面向解释器开发人员
result = eval(tmp)
print(result)
结果输出:
2023-03-25 10:55:29.167351
datetime.datetime(2023, 3, 25, 10, 55, 29, 167351)
2023-03-25 10:55:29.167351
实例6:__call__
# 使对象具备被调用的能力
class Person:
def __call__(self, *args, **kwargs): # 功能是使对象具备被调用的能力
print('xxx', args, kwargs)
pass
p = Person()
p(123, 456, name='sz')
结果输出:
xxx (123, 456) {'name': 'sz'}
实例7: 偏函数functools
使用方法
def createPen(p_color, p_type):
print('创建了一个%s这个类型的画笔,它是%s颜色' % (p_type, p_color))
createPen("钢笔", '红色')
import functools
gangbiFunc = functools.partial(createPen, p_type="钢笔")
gangbiFunc(p_color='红色')
gangbiFunc('蓝色')
gangbiFunc('黑色')
结果输出:
创建了一个红色这个类型的画笔,它是钢笔颜色
创建了一个钢笔这个类型的画笔,它是红色颜色
创建了一个钢笔这个类型的画笔,它是蓝色颜色
创建了一个钢笔这个类型的画笔,它是黑色颜色
实例8:__call__
使用场景
class 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("红色")
gangbiF('绿色')
qianbiF = PenFactory("铅笔")
qianbiF('蓝色')
qianbiF('黄色')
结果输出:
创建了一个钢笔这个类型的画笔,它是红色颜色
创建了一个钢笔这个类型的画笔,它是绿色颜色
创建了一个铅笔这个类型的画笔,它是蓝色颜色
创建了一个铅笔这个类型的画笔,它是黄色颜色
python面向对象-索引操作
a) 增、改、查、删
class Person:
def __init__(self):
self.cache = {}
def __setitem__(self, key, value):
self.cache[key] = value
def __getitem__(self, item):
return self.cache[item]
def __delitem__(self, key):
del self.cache[key]
pass
p = Person()
p['name'] = 'sz' # 增
print(p['name']) # 查
p['name'] = 'nn' # 改
print(p.cache)
del p['name'] # 删
print(p.cache)
结果输出:
sz
{'name': 'nn'}
{}
b) 切片操作
class Person:
def __init__(self):
self.items = [1, 2, 3, 4, 5, 6, 7, 8]
def __setitem__(self, key, value):
self.items[key] = value
def __getitem__(self, item):
print('getitem', item)
def __delitem__(self, key):
print('delitem', key)
p = Person()
p[0: 4: 2] = [1, 2] # 替换操作
print(p.items)
结果输出
[1, 2, 2, 4, 5, 6, 7, 8]
c) 比较操作
实例1
class Person:
def __init__(self, age, height):
self.age = age
self.height = height
def __eq__(self, other): # 相等操作
print(other)
return self.age == other.age
def __ne__(self, other): # 不等操作
print('XXX')
def __len__(self, other): # 小于等于
pass
def __ge__(self, other): # 大于等于
pass
def __lt__(self, other): # 小于
pass
pass
p1 = Person(18, 120)
p2 = Person(19, 110)
print(p1 == p2)
print(p1 != p2)
结果输出:
<__main__.Person object at 0x0000015A85177F70>
False
XXX # 不等于调用 `__ne__(self, other)`
None # 没有return
实例2:
class Person:
def __init__(self, age, height):
self.age = age
self.height = height
def __eq__(self, other): # 相等操作
print(other)
return self.age == other.age
def __ne__(self, other): # 不等操作
print('XXX')
def __le__(self, other): # 小于等于
pass
def __ge__(self, other): # 大于等于
pass
def __lt__(self, other): # 小于
print('lt')
return self.age < other.age
pass
p1 = Person(18, 120)
p2 = Person(19, 110)
print(p1 == p2)
print(p1 < p2)
结果输出:
<__main__.Person object at 0x0000027BD22E7F70>
False
lt
True
实例3:
import functools
@functools.total_ordering # 根据已知的内置方法,补充其他的方法
class Person:
def __lt__(self, other): # 小于
print('lt')
pass
def __eq__(self, other): # 等于
print('eq')
pass
def __le__(self, other): # 小于等于
print('le')
p1 = Person()
p2 = Person()
print(p1 <= p2)
print(Person.__dict__)
结果输出:
le
None
{'__module__': '__main__', '__lt__': <function Person.__lt__ at 0x0000020E91D8C4C0>, '__eq__': <function Person.__eq__ at 0x0000020E91D8C700>, '__le__': <function Person.__le__ at 0x0000020EAAB51550>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, '__hash__': None, '__gt__': <function _gt_from_lt at 0x0000020E91FC2160>, '__ge__': <function _ge_from_lt at 0x0000020E91FC2280>}
python面向对象-比较操作(上下文布尔值)
class Person:
def __init__(self):
self.age = 18
def __bool__(self):
return self.age >= 18
pass
p = Person()
if p:
print('xx')
结果输出:
xx
python面向对象-遍历操作
实例1
class Person:
def __init__(self):
self.result = 1
def __iter__(self):
print('iter')
return self
def __next__(self):
self.result += 1
if self.result >= 6:
raise StopIteration('stop iteration')
return self.result
pass
p = Person()
for i in p: # 首先用iter,再使用next获取数据,直到抛出异常为止
print(i)
实例2
class Person:
def __init__(self):
self.result = 1
# def __iter__(self):
# print('iter')
# return self
def __next__(self):
self.result += 1
if self.result >= 6:
raise StopIteration('stop iteration')
return self.result
pass
p = Person()
print(next(p)) #
print(next(p))
print(next(p)) #
print(next(p))
print(next(p)) #
print(next(p))
结果输出:
2
3
4
5
Traceback (most recent call last):
File "D:\public\python_exam\hello.py", line 1985, in <module>
print(next(p)) #
File "D:\public\python_exam\hello.py", line 1974, in __next__
raise StopIteration('stop iteration')
StopIteration: stop iteration