一、内置类函数
声明类的时候系统会自动添加的属性(可能会是字段也可能是对象自己)
__name__、__slots__、__class__、__dot__、__dict__、__module__
定制当前对象的打印
class Person:
"""
说明文档:人类
num - 人类的数量
name - 人的名字
""""
num = 61
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def eat(self, food):
print('%s在吃%s' % (self.name, food))
# 定制当前对象的打印
# 1)重写__str__方法
def __str__(self):
# return '姓名:{},年龄:{},性别:{}'.format(self.name, self.age, self.gender)
return '<' + str(self.__dict__)[1:-1] + '>'
# 2)重写__reper__方法
# def __repr__(self)
def __repr__(self):
return '<' + str(self.__dict__)[1:-1] + 'id: ' + hex(id(self)) + '>'
p1 = Person('小明', '男', 18)
print(p1)
# <'name': '小明', 'gender': '男', 'age': 18>
1. __name__
__name__指的是类的字段
print(type(Person), person)
print(int)
print(Person.__name__) # 没有p1.__name__
print(type(Person.__name__))
"""
<class 'type'> <class '__main__.Person'>
<class 'type'>
Person
<class 'str'>
"""
2.__dot__
'doc'指的是说明文档
print(Person.__doc__)
# print(int.__doc__)
print(p1.__doc__)
"""
说明文档:人类
num - 人类的数量
name -人的名字
说明文档:人类
num - 人类的数量
name -人的名字
"""
3.__class__
__class__指的是对象属性;
对象.__class__ —— 获取对象对应的类(和type(对象)功能一样)
print(p1.__class__)
print(type(p1))
type1 = p1.__class__ # type1可以当做Person来用
print(type1.__name__)
p2 = type1('小花', '女', 17)
print(p2.name, p2.gender, p2.age)
"""
<class '__main__.Person'>
<class '__main__.Person'>
Person
小花 女 17
"""
4.__dict__(将对象转换成字典)
对象属性;对象.__dict__ —— 将字典中所有的属性以属性和对应的值转换成一个字典中的键值对(一个对象一个字典)
类的字段;类.__dict__ —— 将类转换成一个字典,字典中的元素是类中所有的字段对应的值
print(p1.__dict__)
print(Person.__dict__)
print(p1)
persons = [p1, p2] # 因为__repr__的方法
print(persons)
"""
{'name': '小明', 'gender': '男', 'age': 18}
{'__module__': '__main__', '__doc__': '\n 说明文档:人类\n num - 人类的数量\n name -人的名字\n ', 'num': 61, '__init__': <function Person.__init__ at 0x000000000279F0D8>, 'eat': <function Person.eat at 0x000000000279F168>, '__str__': <function Person.__str__ at 0x000000000279F1F8>, '__repr__': <function Person.__repr__ at 0x000000000279F288>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
<'name': '小明', 'gender': '男', 'age': 18>
[<'name': '小明', 'gender': '男', 'age': 18,id:0x279e848>, <'name': '小花', 'gender': '女', 'age': 17,id:0x279e948>]
"""
5.__module__
__module__是类的字段;类.__module__ —— 获取当前类是在那个模块中声明的返回的是模块的名字
print(Person.__module__)
print(bool.__module__)
print(p1.__module__)
"""
__main__
builtins
__main__
"""
6.__bases__
__bases__类的字段;类.__bases__ —— 获取当前类的父亲(返回的是一个元组)
print(Person.__bases__)
"""
(<class 'object'>,)
"""
练习将数据转换成对象
import json
with open('data.json', 'r', encoding='utf-8') as f:
content = json.loads(f.read())
datas = content
class Data:
# 注意:如果设置了__slots__的值,那么当前类的对象就不能使用__dict__属性
# __slots__ = ('name', 'age', 'dict1')
def __init__(self, dict1: dict):
for key in dict1:
steattr(self, key, dict1[key])
def __repr__(self):
return '<' + str(self, __dict__)[1:-1] + '>'
for item in datas:
data = Data(item)
print(data.name, '\n', data)
"""
a0
<'name': 'a0', 'pwd': '12345', 'add': [], 'alter': [], 'del': [{'name': 'stu0', 'age': 10, 'phone': '12345678901', 'time': 1565170335.1302288}]>
b
<'name': 'b', 'pwd': '45678'>
"""
####二、私有化
######1.访问权限:公开、保护、私有
```python
公开 - 公开的属性和方法在类的内部、外部能够使用,也能继承
保护 - 保护的属性和方法在类的内部能够使用,外部不能使用,可以被继承
私有 - 私有的属性和方法只能在类的内部使用,外部不能使用,也不能被继承
2.python中属性和方法的访问权限
python类中所有的属性和方法本质都是公开的;私有化是假的私有化,只是提示程序员这个属性和方法在外部不能使用,也不能被继承
在需要私有化的属性名或者方法名前加'__'(不能以'__'结尾)
python私有化的原理:在私有的属性和方法前加了'_类名'
class Person:
__num = 61
def __init__(self, name, age):
self.name = name
self.__age = age
self.func1()
def eat(self, food='米饭'):
print('%s吃%s' % (self.name, food))
print('内部num', self.__num)
self.func1()
def func1(self):
print('函数')
print('内部age:', self.__age)
def __func2(self):
print('私有函数')
p1 = Person('小明', 20)
# print(Person.num, p1.name, p1.age)
# p1.eat()
# print(p1.__num) # AttributeError: type object 'Person' has no attribute 'num'
# p1.eat('西瓜')
# p1.func2() # AttributeError: 'Person' object has no attribute 'func2'
p1.eat()
p1.func1()
print(Person.__dict__)
print(p1.__dict__)
# print(p1._Person__age) # 不建议使用
"""
函数
内部age: 20
小明吃米饭
内部num 61
函数
内部age: 20
函数
内部age: 20
{'__module__': '__main__', '_Person__num': 61, '__init__': <function Person.__init__ at 0x0000000002784EE8>, 'eat': <function Person.eat at 0x0000000002784F78>, 'func1': <function Person.func1 at 0x000000000278E048>, '_Person__func2': <function Person.__func2 at 0x000000000278E0D8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
{'name': '小明', '_Person__age': 20}
"""
三、属性的getter和setter
1.什么是getter和setter
当我们需要在获取属性值之前做点别的事情就需要给这个属性添加getter
当我们需要给属性值赋值之前做点别的事情,就需要给这个属性添加setter
2.给属性添加getter
1)属性命名的时候在前面加一个下划线_
2)在@property装饰器的后面声明一个对象方法
a. 将属性去掉下划线作为方法名
b.方法除了self外不需要其他参数
c.函数的返回值就是获取这个属性的时候得到的值
3)在外部使用属性的时候,通过对象.不带下划线的属性去使用
注意:获取属性值的时候,就会自动调用getter对应的函数
3.给属性添加setter
属性添加setter之前必须先添加getter
1)保证属性名前有一个_
2)在@getter名.setter后面声明函数
a.将属性去掉下划线作为方法名
b.需要一个self以外的参数
c.不需要返回值
3)在外部使用属性的时候,通过'对象.不带下划线的属性'去使用
注意:当给属性赋值的时候,实质是调用setter对应的方法
class Person:
count = 0
def __init__(self, name, age, gender):
self.name = name
self._age = age
self._gender = gender
self._week = 0
# 添加getter
@property
def week(self):
if self._week == 0:
return '星期天'
if self._week == 1:
return '星期一'
if self._week == 2:
return '星期二'
if self._week == 3:
return '星期三'
if self._week == 4:
return '星期四'
if self._week == 5:
return '星期五'
if self._week == 6:
return '星期六'
# return 'abc'
# return self._week
@property
def age(self):
Person.count += 1
print('年龄值被访问!', Person.count)
return self._age
@age.setter
def age(self, value):
print('年龄值被修改!!!')
if not isinstance(value, int):
raise ValueError
if not 0 <= value <= 200:
raise ValueError
# print('~~~~~~~')
# print('value: ', value)
self._age = value
@property
def gender(self):
# return self._gender
if self._gender == 1:
return '女'
if self._gender == 0:
return '男'
@gender.setter
def gender(self):
return ValueError
p1 = Person('小米糕', 18, '女')
# p1.age = 1908
# p1.age = 'abc'
# print(p1.name, p1.age, p1.gender, p1.week)
print(p1.week) # 这儿实质就是在调用week方法获取返回值
p2 = Person('小花', 20, '男')
print(p1.age) # p1.age()
age1 = p1.age
print(p2.age) # p2.age()
p1.age = 200 # p1.age(200)
"""
星期天
年龄值被访问! 1
18
年龄值被访问! 2
年龄值被访问! 3
20
年龄值被修改!!!
"""
练习:写一个矩形类
有属性:长、宽、面积和周长
要求从生活的角度看这个矩形
class WriteError(Exception):
def __str__(self):
return '修改只读属性'
class Rect:
def __init__(self, width, length):
self._width = width
self._length = length
self._area = 0
self._perimeter = 0
@property
def length(self):
return self._length
@length.setter
def length(self, value):
if not isinstance(value, int) and not isinstance(value, float):
raise ValueError
if value < 0:
raise ValueError
self._length = value
@property
def width(self):
return self._width
@width.setter
def width(self, value):
if not isinstance(value, int) and not isinstance(value, float):
raise ValueError
if value < 0:
raise ValueError
self._width = value
@property
def area(self):
self._area = self._length * self._width
return self._area
@area.setter
def area(self, value):
raise WriteError
@property
def perimeter(self):
self._perimeter = 2 * (self._length + self._width)
return self._perimeter
@perimeter.setter
def perimeter(self, value):
raise WriteError
rect1 = Rect(1, 2)
print(rect1.area)
print(rect1.perimeter)
rect1.length = 3
print(rect1.area)
print(rect1.perimeter)
# rect1.area = 22
# print(rect1.area)
"""
2
6
3
8
"""
####四、类方法和静态方法
######1.类中的函数
类中的方法分为:对象方法、类方法、静态法
1)对象方法
a.怎么声明:直接声明
b.怎么调用:用对象来调用
c.特点:有指向当前对象的`self`
d.什么时候用:如果实现函数的功能需要用到对象属性,就是引用对象方法
2)类方法
a.怎么声明:声明在@classmethod后面
b.怎么调用:用类来调用,`类.类方法()`
c.特点:有自带的参数`cls`,表示当前类;这个参数在调用的时候不用传参,系统会自动将当前类传给它;
`cls`:谁调用就指向谁(如果是对象指向的是对象对应的类)
d.什么时候用:如果实现函数的功能不需要属性对象属性,但需要类的字段,就使用类方法
3)静态方法
a.怎么声明:声明在@staticmethod的后面
b,怎么调用:通过类来调用,`类.静态方法()`
c.特点:没有默认参数
d.什么时候用:实现函数的功能既不需要类又不需要对象额,就是用静态方法
```python
class Person:
num = 61
def __init__(self, name: str, age: int, gender: str):
self.name = name
self.age = age
self.gender = gender
def eat(self, food: str):
# 对象能做的事情,self都能做
print(self.name + '在吃' + food)
@classmethod
def func1(cls):
# 类能做的事情,cls都能做
print(cls)
t = cls('a', 10, '男')
print('t:', t)
print(cls.num)
print('这是一个类方法!')
@staticmethod
def func2():
print('这是一个静态方法!')
def func3(self):
print('这是一个函数!', self.name)
def func4(self):
print(self.age, Person.num)
print(Person)
Person.func1()
p1 = Person('西西里', 90, '女')
p1.func1()
Person.func2()
p1.func3()
p1.func4()
print('=' * 60)
class Student(Person):
num = 10
print('====================1============================')
Student.func1()
Person.func1()
print('====================2============================')
Student.func2()
Person.func2()
"""
<class '__main__.Person'>
<class '__main__.Person'>
t: <__main__.Person object at 0x00000000027FD388>
61
这是一个类方法!
<class '__main__.Person'>
t: <__main__.Person object at 0x00000000027FD408>
61
这是一个类方法!
这是一个静态方法!
这是一个函数! 西西里
90 61
============================================================
====================1============================
<class '__main__.Student'>
t: <__main__.Student object at 0x00000000027FD408>
10
这是一个类方法!
<class '__main__.Person'>
t: <__main__.Person object at 0x00000000027FD448>
61
这是一个类方法!
====================2============================
这是一个静态方法!
这是一个静态方法!
"""
五、继承
1.什么是继承
继承就是让子类直接拥有父类的属性和方法
子类 —— 继承者
父类 / 超类 —— 被继承着
2.怎么继承
1)语法
class 类名(父类1, 父类2, ...):
说明文档
类的类容
2)说明
() —— 固定写法,如果省略相当于(object)
声明类的时候如果没有写父类,默认继承object(object又叫基类)
父类 —— 一个类的分类可以有多个,一般情况下只有一个(支持多继承)
class Person:
num = 61
def __init__(self):
print('Person中的init')
self.name = '小明'
self.age = 18
self.gender = '男'
self.__a = 12
def eat(self, food='米饭'):
print('{}在吃{}'.format(self.name, food))
@classmethod
def show(cls):
print('人类的数量:%d' % cls.num)
@staticmethod
def func1():
print('人类')
def func2(self):
print('我是' + self.name)
class Student(Person):
num = 10 # 重写
def __init__(self):
print('Student中的init')
self.study_id = '001'
self.classes = 'py'
# 在子类中添加对象属性,需要先通过super去调用父类的__init__来继承父类的对象属性
super().__init__()
@staticmethod
def func1():
print('学生')
def func2(self):
print('我是学生')
# 在子类中可以通过super方法可以去调用父类的方法
# 注意:super()只能在对象方法和类方法中使用,静态方法用不了
super(Student, self).func2()
# 添加功能
def study(self):
print(self.name + '在好好学习!')
stu1 = Student()
print(stu1.num)
print(stu1.name, stu1.age, stu1.gender)
stu1.eat()
Student.show()
print(stu1.__dict__)
stu1.func1()
stu1.func2()
# import sys
# print(sys.stdout.flush())
"""
Student中的init
Person中的init
10
小明 18 男
小明在吃米饭
人类的数量:10
{'study_id': '001', 'classes': 'py', 'name': '小明', 'age': 18, 'gender': '男', '_Person__a': 12}
学生
我是学生
我是小明
"""
``