2018-09-07 类和对象(2)
01-recode
1.类声明
class 类名
——说明文档
——类的内容
2.怎么声明对象
对象 = 类名
3._ init _函数
a.自动调用(当创建对象的时候)
b.通过构造方法给init方法传参
c.想要声明对象的属性,必须要有init方法
4.对象的属性
a.不同的对象对应的值可能不一样
b.声明在init方法中
c.self.属性名 = 初值
d.通过对象使用
5.对象属性的增删改查(查,改)
6.对象方法
a.直接声明在类中,并且带一个默认的参数self
b.调用对象方法不需要给self传参,系统会自动把当前对象传给它,谁调用这个方法,self就指向谁
c.对象方法中的self可以当成当前类的对象使用
7.类的字段
a.声明在类中的变量
b.通过类去使用:类.字段
8.类方法
a.@class method来说明,自带一个cls参数
b.cls参数调用的时候不需要传参,谁调用这个方法就指向谁,永远指向当前类
c.通过类调用
9.a.@statimethod来说明,没有默认参数
b.通过类调用
02-内置类属性
内置类属性就是魔法属性
魔法属性:属性名的前面和后面都有两个下划线
魔法方法:方法的前后都有两个下划线
import datetime
class Person:
'''人的类'''
# 类的字段
number = 61
def __init__(self,name1,age1,height1):
# 对象的属性
self.name = name1
self.age = age1
self.height =height1
def run(self):
print('%s在跑步'% (self.name))
#类方法
@classmethod
def show_number(cls):
print('人类的数量为:%d亿'% (cls.number))
# 静态方法
@staticmethod
def destroy():
print('人类在破坏环境!')
if __name__ == '__main__':
p1 = Person('张三丰',20,173)
1.name属性 --- 类的名字(是字符串)
# 类的属性
name = Person.__name__
print(name,type(name))
2.class属性 --- 获取对象对应类(是一个类)
# 对象的属性
# my_classs是一个类,之前类能做的事情他都能做
my_class = p1.__class__
p2 = my_class('小明',20,100)
print(p2.name)
3.dict属性 --- 将对象和类的属性及其对应的值转换成键值对存到一个字典中
# print(Person.__class__)
print(p1.__dict__) # {'name': '张三丰', 'age': 20, 'height': 173}
4.doc属性----获取类的说明文档
# 类的属性
doc = Person.__doc__
print(doc)
5.module属性 ---- 获取所有模块对应的名字
print(Person.__module__)
print(datetime.datetime.__module__)
6.bases属性 ---获取当前类的父类
# 类的属性
print(Person.__bases__)
03-slots魔法
class Person:
'''人的类'''
# 通过__slots__中存的元素的属性的值来约束当前这个类的对象的属性,对象的属性只能比元组中的少,不能多
__slots__ = ('name','age','face')
def __init__(self):
# 对象的属性
self.name = '张三丰'
self.age = 20
self.face = 80
# self.sex = 'boy' # __slots__中并没有sex
if __name__ == '__main__':
p1 = Person()
# p1.sex = 'girl'
# print(p1.sex)
# p1.name = '小明'
print(p1.name)
# 注意:一旦在类中给__slots__属性赋了值,那么这个类的对象的__dict__属性就不能使用了
# print(p1.__dict__)
04-私有化
python中并没有真正的私有化
1.私有化的语法
a.类中的属性和方法都可以通过在属性名和方法名前加两个下划线,来让属性和方法变成私有的
b.私有的属性和方法只能在当前的类中使用
2.私有化的原理
在前面有两个下划线的属性名和方法名前添加了'_类名'来阻止外部直接访问属性名来使用属性
class Dog:
# 字段
number = 100
__count = 200
def __init__(self):
# 对象的属性
self.color = '黄色'
self.age = 3
self.name = '大黄'
self.__sex = '公狗'
# 对象方法
def __eat(self):
print('%s啃骨头'% (self.name))
def eat(self):
# 在类中可以使用私有的属性
self.__eat()
print('%s在吃屎·' % (self.name))
# 类方法
@classmethod
def shout(cls):
print('count',cls.__count)
print('汪汪汪~~~')
# 静态方法
@staticmethod
def function():
print('看家!!')
# python的类中默认的属性和方法是公开的
dog1 = Dog()
print(Dog.number)
print(dog1.name,dog1.color,dog1.age)
dog1.eat()
Dog.shout()
Dog.function()
# 在类的外面不能使用私有属性
# print(Dog.__count) AttributeError: type object 'Dog' has no attribute '__count'
# print(dog1.__sex) AttributeError: 'Dog' object has no attribute '__sex'
dog1.eat()
print(dog1.__dict__)
05-属性的getter和setter
1.解释
a.保护类型的属性:就是在声明对象属性的时候在属性名前加一个下划线来代表这个属性是受保护的属性,
那么以后访问这个属性的时候就不要直接访问,要通过getter来获取这个属性的值,通过setter来给这个属性赋值
b.如果一个属性已经声明成保护类型的属性,那么我们就要给这个属性添加getter,也可以添加setter
2.添加getter
添加getter就是声明一个没有参数,有一个返回值的函数
a.格式:
@property
def 去掉下划线的属性名(self):
——函数体
——将属性相关的值返回
b.使用场景
场景一:如果想要获取对象的某个属性的值之前,想要做其他处理,就可以给这个属性添加getter
场景二:想要拿到某个属性被使用的时刻
3.添加setter
添加setter就是声明一个有一个参数,但是没有返回值的参数,作用是给属性赋值
a.格式
b.使用场景
在给属性赋值前要进行其他操作,就给属性声明一个setter函数
class Car:
def __init__(self):
self.color = '黄色'
self.type = '自行车'
# price是保护类型
self._price = 2000
# 给_price属性添加getter
@property
def price(self):
print('在使用_price属性')
return self._price/1000
# 想要给一个属性添加setter,就必须先给这个属性添加getter
@price.setter
def price(self,price):
if isinstance(price,int) or isinstance(price,float):
self.price
else:
self._price = 0
练习:声明一个员工类,其中一个属性是否已婚(bool),获取值之前根据存的值返回"已婚"/"未婚"
class Staff:
'''员工类'''
def __init__(self,name,age):
self.name =name
self.age = age
self._is_marry = False
@property
def is_marry(self):
print('在使用_price属性')
if self._is_marry:
return '已婚'
return '未婚'
@is_marry.setter
def is_marry(self, marry):
self._is_marry = marry
if __name__ == '__main__':
car1 = Car()
print(car1.color,car1._price)
# 添加完getter后就通过getter去获取属性值,实质就是调用getter对应方法
# price就是属性_price的getter
print(car1.price,'k')
# 通过setter给属性赋值,实质是调用setter对应的方法
car1.price= 'abc'
print(car1.price)
s1 = Staff('张三', 20)
print(s1.is_marry)
s1.is_marry = True
print(s1.is_marry)
06-继承
python中类可以继承,并且支持多继承
程序中的继承:就是让子类字节拥有父类的属性和方法(继承父类中的内容不会因为被继承而减少)
1.继承的语法
class 子类(父类):
类的内容
注意:如果声明类的时候没有写继承,那么这个类会自动继承python中的基类,object;相当于class 类名(object):
python中所有的类都是直接和间接的继承自object
2.能继承那些东西
a.所有的属性和方法都能继承
b.slots的值不会继承,但是会影响子类对象的dict属性,不能获取父类继承下来的属性
class Person:
'''人类'''
# 字段
number = 61
# __slots__ = ('name','age')
# 对象属性
def __init__(self,name='张三',age=18):
self.name = name
self.age = age
self._height = 173
# 对象方法
def show_message(self):
print('姓名:%s 年龄:%d'% (self.name,self.age))
@classmethod
def show_number(cls):
print('人类的数量:%d亿'% cls.number)
@staticmethod
def show_message():
print('人类殴打小动物!')
class Student(Person):
'''学生类'''
pass
#创建Person类的对象
p = Person()
# 学生类
stu1 = Student()
print(Student.number)
print(stu1.name)
stu1.show_number()
stu1.show_message()
print(stu1.__dict__)
if __name__ == '__main__':
pass
07-方法的重写
子类继承父类,拥有父类的属性和方法以后,还可以添加自己的属性和方法
1.添加方法和类的字段
直接在子类中声明相应的字段和方法
2.添加对象属性
对象的属性是通过继承父类的init方法而继承下来
如果想要保留父类的对象的同时添加自己的对象属性,需要在子类的init方法中通过super()去调用父类的init方法
3.方法的重写
在子类中重新实现父类的方法,就是重写
方式一:直接覆盖父类的实现
方式二:保留父类的功能再添加其他功能
4.类中方法的调用过程
先在当前这个中的去找,没有找到就去父类中找,还是没找到就去,就去父类的父类中去找,以此类推,如果在基类中也没找到,才崩溃
在第一次找到的位置,去调用
注意:使用super的时候必须通过super()来代替父类或者是父类的对象
class Animal:
'''动物'''
def __init__(self):
self.age = 0
self.sex = '雌'
def shout(self):
print('嗷嗷叫')
class Cat(Animal):
'''猫'''
def __init__(self):
# 调用父类的init方法
super().__init__()
self.name = '小花'
food = '鱼'
def shout(self):
print('喵喵喵~~~')
class Dog(Animal):
'''狗'''
def shout(self):
# 通过super()调用父类的方法,保留父类功能
super().shout()
print('汪汪汪~~~')
cat1 = Cat()
print(cat1.name,cat1.age,cat1.sex)
cat1.shout()
dog1 = Dog()
dog1.shout()
08-init方法的重写
练习:写一个人类,拥有属性name,age,sex。要求创建Person对象的时候必须给name和age赋值,sex可赋可不赋,再写一个Staff类继承自Person类,要求保留Person中所有的属性,并且添加新的属性salary,要求创建Staff类的对象的时候,只能给name赋值(必须赋)
class Person:
'''人类'''
def __init__(self,name,age,sex='boy'):
self.name = name
self.age =age
self.sex = sex
class Staff(Person):
def __init__(self,name):
super().__init__(name,20)
self.salary = '10000'
if __name__ == '__main__':
p1 = Person('张三',20)
s1 = Staff('李四')
09-运算符的重载
如果希望类的对象支持相应的运算符(+,-,*,/,>,<ect),就必须实现相应的魔法方法
继承一样有用
- : daa
:gt
一般情况需要对>或者<进行重载,重载后可以通过sort方法直接对对象的列表进行排序
class Student:
def __init__(self,name='',age=0,score=0):
self.name = name
self.age = age
self.score = score
# self:+ 前面的对象
# other:+ 后面的对象
def __add__(self, other):
return self.score + other.score
# 重载 > 符号
# 注意:重载>和<可以只重载一个,另一个对应的功能自动取反
def __gt__(self, other):
return self.age > other.age
# 重写魔法方法__str__,用来制定对象的打印样式
def __str__(self):
return 'Student:%s %d %d'% (self.name,self.age,self.score)
if __name__ == '__main__':
stu1 = Student('小明',18,90)
stu2 = Student('老王',29,84)
stu3 = Student('项羽',24,70)
print(stu1 + stu2)
print(stu1 > stu2)
print(stu1 < stu2)
all_student = [stu1,stu2,stu3]
all_student.sort()
for stu in all_student:
print(stu.name,stu.age,stu.score)
print(stu1.__str__())