day15属性类方法继承

私有化

本质上,python中所有的属性和方法都是公开的,在类的外部可以使用和继承
1.私有化 - 让属性和方法只能在类的内部使用,不能在类的外部使用
语法:
声明属性或者方法的时候,在属性名或者方法名前加‘_
python私有化的原理:
python并不能像java一样从访问全线上去限制属性和方法,没有真正的私有属性和方法
私有化只是在两个下划线开头的名字前加前缀'
类名',导致不能直接通过原名进行访问

class Person:
    __num = 30  # 私有化

    def __init__(self, name, gender, age=10):
        self.name = name
        self.age = age
        self.__gender = gender

    def eat(self, food='米饭'):
        print('%s在吃%s' % (self.name, food))
        print(Person.__num)  # 在内部使用私有化变量
        print(p1.__gender)


p1 = Person('小明', '男', 25)
p1.eat()

2.对象属性的保护:不要直接访问或者修改对象属性的值,
而是通过属性访问器(getter)和修改器(setter)操作对象属性

需要添加getter或者setter的对象属性,属性命名的时候需要在前面加上'_',
添加下划线的目的是告诉使用者,这个属性我给它加了getter或者setter

getter: - 获取属性的值(间接)
语法:
@property
def 函数名(self):
其他语句
return 属性值
说明 - 对应的属性名去掉下划线
属性值 - 和对应的下划线的属性值有关联
什么时候使用:
如果希望在获取某属性的值之前做点什么事

setter - 给属性赋值(间接赋值)
想要添加setter必须先添加getter
语法:
@getter名.setter
def 函数名(self, 参数)
其他语句
self.属性 = 参数

什么时候使用:
如果在给属性赋值的之前想干点别的事

class Student:
    def __init__(self, name):
        self._name = name
        self._week = 1
        self._age = 18

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self.age

    @age.setter
    def age(self, value):
        if isinstance(value, int):
            if value < 0 or value > 200:
                print('年龄只能在0-200之间')
                self._age = 0
            else:
                self._age = value
        else:
            print('年龄只能是整数!')
            self._age = 0

    @property
    def week(self):
        if self._week == 1:
            return '星期一'
        elif self._week == 2:
            return '星期二'
        elif self._week == 3:
            return '星期三'
        elif self._week == 4:
            return '星期四'
        elif self._week == 5:
            return '星期五'
        elif self._week == 6:
            return '星期六'
        elif self._week == 7:
            return '星期日 '


stu1 = Student('小明')
# print(stu1._name)  无法获取到name
print(stu1.name)   # 获取通过不带下划线去获取属性值的时候,本质是在调用属性值对应的getter方法,获取返回值
print(stu1.week)
stu1.age = 150

练习:声明矩形类,有属性:长宽,周长,面积要求修改长和宽的值的时候,周长和面积自动变化并且不能修改周长和面积的值(如果直接给周长和面积赋值,程序直接报错)

class Rect:
    def __init__(self, long, width):
        self._long = long
        self._width = width
        self._perimeter = (long + width) * 2
        self._area = long * width

    @property
    def long(self):
        return self._long

    @long.setter
    def long(self, value):
        self._long = value
        self._perimeter = (self._long + self._width) * 2
        self._area = self._long * self._width

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        self._width = value
        self._perimeter = (self._long + self._width) * 2
        self._area = self._long * self._width

    @property
    def perimeter(self):
        return self._perimeter

    @perimeter.setter
    def perimeter(self, value):
        raise ValueError

    @property
    def area(self):
        return self._area

    @area.setter
    def area(self, value):
        raise ValueError


r1 = Rect(5, 5)
print('周长:', r1.perimeter, '面积:', r1.area)

r1.long = 10
print('周长:', r1.perimeter, '面积:', r1.area)

r1.witth = 10
print('周长:', r1.perimeter, '面积:', r1.area)

类中的方法

1.类中的方法:对象方法、类方法、静态方法

对象方法:
a.怎么声明:直接声明在类中
b.特点:自带self参数,调用的时候不用传参,指向当前对象
c.怎么调用:对象. 的方式调用
d.什么时候使用:如果实现函数的功能,需要使用对象属性,就用对象方法

类方法:
a.怎么声明:声明函数前添加@classmethon装饰器
b.特点:有默认cls参数,调用的时候不传参,系统将调用这个方法的类传给它,指向当前类
c.怎么调用:通过类来调用
d.什么时候使用:在不需要对象属性的前提下,需要类的字段,就用类方法

静态方法:
a.怎么声明:声明前添加@staticmethod装饰器
b.特点:没有默认参数
c.怎么调用:通过类调用
d.什么时候使用:既不需要对象的属性,也不需要类的字段,就是用静态方法

class Person:
    num = 60

    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 对象方法

    def eat(self, food='屎'):
        print('%s 在吃 %s' % (self.name, food))

    # 类方法
    @classmethod
    def show(cls):
        print('这是一个类方法')
        # cls:当前类能做的事情,cls都能做
        print(cls.num)  # 使用类的字段
        p2 = cls('大黄', 29)  # 创建对象
        print(p2.__dict__)

    # 静态方法
    @staticmethod
    def static():
        print('这是一个静态方法')


p1 = Person('小明', 28)
p1.eat()  # 调用对象方法
Person.show()  # 通过类调用类方法
Person.static()  # 通过类调用静态方法

继承

1.继承
继承者 - 子类
被继承者 - 父类
继承 - 就是让子类拥有父类的属性和方法

语法:
class 类名(父类):
类的内容

2.在子类中添加内容
在子类中添加字段和方法:
直接在子类中声明新的字段和方法

添加对象属性:
在子类中实现init方法,添加新属性,同时通过super().init()调用父类的init方法

补充:类中函数调用的过程
先看当前类中是否有这个方法,如果有直接调用自己的方法,如果没有就去看父类有没有这个方法,
如果有就调用父类的方法,如果父类也没有找到父类的父类,以此类推,如果找到object都没有找到这个
方法才会报错
python中的所有类都默认继承object, object是python所有类的基类

3.重写
在子类中重写父类的方法:
可以通过super()去调用父类的方法
注意:super()不能在静态方法中使用,只能在对象方法和类方法中使用

class Person:
    num = 61

    def __init__(self):
        self.name = '张三'
        self.age = 0
        self.gender = '女'

    def eat(self, food):
        print('%s 在吃 %s ' % (self.name, food))

    @staticmethod
    def run():
        print('人跑步')


class Student(Person):
    num = 100  # 重写
    id_pre = 'stu'

    @staticmethod
    def study():
        print('好好学习,天天吃饭')

    def __init__(self):
        super().__init__()  # 调用父类的__init__方法
        self.stu_id = '001'
        self.score = 0

    @classmethod
    def run(cls):
        print('++++++子类继承父类方法+++++++')
        super().run()  # 调用父类的方法
        print('学生跑步')


print(Student.num)
stu = Student()
print(stu.name, stu.age, stu.gender)
stu.eat('蟑螂')
Student.study()
print(stu.name, stu.stu_id)
Person.run()
Student.run()
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容