2018-09-07day15类和对象总结
1.内置类属性
内置类属性就是魔法属性
魔法属性:属性名的前面和后面都有两个下划线
魔法方法:方法的前后都有两个下划线
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("人类的数量为:%亿" % cls.number)
#静态方法
@staticmethod
def destroy():
print("人类在破坏环境")
p1 = Person("张三",25,175)
1.name属性
name = Person.__name__
print(name,type(name))
2._classs属性
对象的属性,
my_class是一个类,之前类能做的事他都能做
my_class = p1.__class__
p2 = my_class("小明",20,175)
dict属性---将对象属性及其对应的值装换成键值对存到一个字典中
print((Person.__dict__))
4.doc属性--->获取类的说明文档
类的属性
doc= Person.__doc__
print(doc)
5.module属性---获取类所在的模块对应的名字
print(Person.__module__)
print(datetime.datetime.__module__)
6.base属性 --获取当前类的父类
print(Person.__bases__)
2.slots魔法
通过solts中存的元素的属性的值来约束当前这个类的对象的属性
对象的属性只能比元组中的元素少,不能多
class Person:
__slots__ = ("name","age","face")
def __init__(self):
self.name = "张三"
self.age = 20
self.face = 70
#self.sex = "boy" #__slots__中并没有sex
p1 = Person()
# p1.sex = "girl"
# print(p1.sex)
#
# p1.name = "小明"
print(p1.name)
注意,一旦在类中给slots属性赋了值,那么这个类的对象的dict属性就不能用了
3.属性的私有化
python中并没有真正的私有化
1.私有化
a.类中的属性和方法都可以通过在属性名和方法名前加两个下划线,来让属性和方法变成私有的
b.私有的属性和方法只能在当前的类中使用
2.私有化原理
在前面有两个下划线的属性名和方法名前添加了"_类名"来阻止外部通过直接访问属性名来使用属性
class Dog:
#字段
number = 100
__count = 200
def __init__(self):
#对象的属性
self.color = "黄色"
self.age = 3
self.name = "大黄"
self.sex = "boy"
#对象方法
def eat(self):
#在类中可以使用属性的私有化
# self.__eat()
print("%s在啃骨头" % self.name)
#类方法
@classmethod
def shout(cls):
print("count:",cls.__count,Dog.__count)
print("汪 汪汪")
#静态方法
@staticmethod
def function():
print("看家")
#python的类中默认的属性和方法都是公开的
dog1 = Dog()
print(Dog.number)
print(dog1.name,dog1.age,dog1.color)
dog1.eat()
dog1.shout()
dog1.function()
#在类的外面不能使用属性的私有化
#print(Dog.__count)
# print(dog1.__sex)
# dog1.__eat()
print(dog1._Dog__sex)
print(dog1.__dict__)
#在类的外面不能使用属性的私有化
#print(Dog.__count)
# print(dog1.__sex)
# dog1.__eat()
print(dog1._Dog__sex)
print(dog1.__dict__)
输出:
100
大黄 黄色 3
大黄啃骨头~
大黄在吃屎~
count: 200 200
汪汪汪~~~
看家!!
公狗
{'color': '黄色', 'age': 3, 'name': '大黄', '_Dog__sex': '公狗'}
4.属性的getter和setter
1.保护类型的属性:
a.就是在声明对象属性的时候在属性名前加一个下划线来代表这个属性是受保护的属性,那么以后访问这个属性的时候就不要直接访问,要通过getter来获取这个属性的值,setter来给这个属性赋值
b.如果一个属性已经声明成保护类型的属性,那么我们需要给这个属性添加getter,也可以添加setter
2.添加getter
添加getter其实就是声明一个没有返回值的函数
a.声明的格式:
@property
def 去掉下划线的属性名(self)
函数体
将属性相关的值返回
b.使用场景
1.如果想要在获取对象的某个属性的值前,想要再做点别的事情,就可以给这个属性添加getter
2.想要拿到某个属性被使用的时刻
3.添加setter
添加setter就是声明一个有一个参数但是没有返回值的函数,作用是给属性赋值
class Car:
def __init__(self):
self.color = "黄色"
self.type = "自行车"
#_price是保护类型
self._price = 1000
#给_price属性添加getter
@property
def price(self):
print("保护属性")
return self._price/1000
#想要给一个属性添加setter必须先给这个属性添加getter
@price.setter
def price(self,price):
if isinstance(price,int) or isinstance(price,float):
self._price = price
else:
self.price = 0
car1 = Car()
print(car1.color,car1._price)
#添加完getter后就通过getter去获取属性的值
#price就是_price的getter
print(car1.price,"k") #实质是在调用getter对应的方法
#通过setter给_price属性赋值,实质是在调用setter对应的方法
car1.price = 3000
print(car1.price)
输出:
黄色 1000
保护属性
1.0 k
保护属性
3.0
保护属性
0.0
练习:声明一个员工类,其中有一个属性是是否已婚(bool)获取值之前根据存的值返回"已婚/未婚"
class Staff:
def __init__(self,name,age):
self.name = name
self.age = age
self._is_married = False
@property
def is_married(self):
if self._is_married:
return "已婚"
else:
return "未婚"
@is_married.setter
def is_married(self,married):
self._is_married = married
staff1 = Staff("咻咻",23)
print(staff1.is_married)
staff1.is_married = True
print(staff1.is_married)
输出:
未婚
已婚
5.继承
python中的类可以继承,并且支持多继承
程序中的继承:就是让子类直接拥有父类的属性和方法,(继承后父类中的内容不会因为继承而减少)
1.继承的语法
class 子类(父类)
类的内容
注意:如果生命类的时候没有写继承,那么这个类会自动继承python的基类object;相当于class类名(object)
python中所有的类都是直接或者间接的继承自object
2.能继承哪些东西
a.所有的属性和方法都能继承
b.slots的值不会继承,但是会影响子类对象的dict属性,不能获取到父类继承下来的属性
class Person:
"""人类"""
#字段
number = 1000
# __slots__ = ("name","age")
#对象属性
def __init__(self,name = "biubiu",age = 20):
self.name = name
self.age = age
self._height = 159
#对象方法
def show_massage(self):
print("姓名:%s 年龄:%d" % (self.name,self.age))
#类方法
@classmethod
def show_number(cls):
print("人类数量:%d" % cls.number)
#静态方法
@staticmethod
def complaint():
print("弄死!!")
class Student(Person):
"""学生类"""
pass
#创建Person类的对象
#创建Student类的对象
stu1 = Student()
print(Student.number)
stu1.name = "咻咻"
print(stu1.name)
stu1.show_massage()
Student.show_number()
Student.complaint()
stu1.sex = "girl"
print(stu1.__dict__)
6.方法的重写
子类继承父类,拥有父类的属性和方法以后,还可以再添加自己的属性和方法
1.添加方法和类的字段
直接在子类中声明相应的方法和字段
2.添加对象属性
对象的属性是通过继承父类的init方法而继承下来
如果想要在保留父类的对象的同时添加自己的对象属性,需要在子类的init方法中通过super()去调用父类的init方法
3.方法的重写
在子类中重新实现父类的方法,就是重写
方式一: 直接覆盖父类的实现
方式二: 保留父类的功能再添加其他功能
4.类中方法的调用过程(重点)
先在当前这个中的去找,没有去父类中找,找不到再去父类的父类中找,依次类推,如在基类中都没有找到才崩溃。
在第一次找到的位置,去调用
注意:使用super的时候必须是通过super()来代替父类或者是父类对象
class Animal:
def __init__(self):
self.age = 1
self.sex = "雌"
def shout(self):
print("嗷呜~~")
def eat(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()
cat1.shout()
print(cat1.name)
print(cat1.age)
dog1 = Dog()
dog1.shout()
7.init方法的重写
练习,写一个Person类,拥有属性name,age,sex,要求创建Person对象的时候必须给name和age赋值,sex可赋可不赋
再写一个Staff类继承自Person类,要求保留Person中所有的属性,并且添加新的属性salary
要求创建Staff类对象的时候,只能给name赋值(必须赋)
class Person:
def __init__(self,name,age,sex = "girl"):
self.name = name
self.age = age
self.sex = sex
class Staff(Person):
def __init__(self,name):
super().__init__(name,20)
self.salary = 8000
p1 = Person("秀秀",21)
p2 = Person("啾啾",23,"男")
s1 = Staff("咻咻")
8.运算符的重载
如果希望类的对象支持相应的运算符操作(例如:+, -, *, /, >, <等),就必须实现相应的魔法方法。
这个过程就叫运算符的重载
一般情况需要对>或者<进行重载,重载后可以通过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 '<%s.%s object at 0x%x>' % (self.__module__, self.__class__.__name__, id(self))
# return 'Student: %s %d %d' % (self.name, self.age, self.score)
return str(self.__dict__)[1:-1]
class Schoolchild(Student):
def __add__(self, other):
return self.age + other.age
if __name__ == '__main__':
stu1 = Student('小明', 18, 90)
stu2 = Student('老王', 29, 84)
stu3 = Student('小花', 20, 78)
print(stu1)
all_students = [stu1, stu2, stu3]
all_students.sort(reverse=True)
for stu in all_students:
print(stu.name, stu.age, stu.score)
print(stu1 > stu2)
print(stu1 < stu2)
print(stu1 + stu2)
print(stu3 > stu1)
# 父类重载了运算符,子类也能用
c1 = Schoolchild('小明明', 8, 70)
c2 = Schoolchild('小花花', 10, 67)
print(c1+c2)
输出:
'name': '小明', 'age': 18, 'score': 90
老王 29 84
小花 20 78
小明 18 90
False
True
174
True
18