day14-类和对象2

14.1 类方法和静态方法

类中方法分为:对象方法,类方法和静态方法

  • 1.对象方法
    a.直接声明在类中
    b.有默认参数self
    c.通过对象调用

  • 2.类方法
    a.在声明前添加@classmethod
    b.有默认参数cls,调用时不需要给cls传参,系统会自动将调用当前类方法的类传给cls
    cls最终指向的是一个类,类可以做的,cls都可以做。
    c.通过类去调用:类.类方法()

  • 3.静态方法
    a.在声明前添加@staticmethod
    b.没有默认参数,
    c.通过类去调用:类.类方法()

  • 4.对对象方法、类方法和静态方法的选择
    a.什么时候使用对象方法:
    当实现函数功能需要用到对象属性时,就使用对象方法。
    b.什么时候使用类方法:
    实现函数功能不需要用到对象属性,但是需要类的时候就使用类方法。
    c.什么时候使用静态方法:
    实现函数功能,既不需要对象属性,也不需要类的时候,就使用静态方法。

class Person:
    pi = 3.1415926

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

    # 对象方法
    def eat(self, food):
        print('%s在吃%s' % (self.name, food))

    # 类方法
    @classmethod
    def destroy(cls):
        print('人类破坏环境。')

        # 可以用cls来创建对象
        p1 = cls('老王')
        p1.eat('牛肉')

        # 使用类的字段
        print(cls.pi)

        # 使用cls调用类相关方法

    # 静态方法
    @staticmethod
    def hit_animal():
        print('人类殴打小动物!')


Person.destroy()        # 人类破坏环境。 老王在吃牛肉 3.1415926
Person.hit_animal()     # 人类殴打小动物!

# 练习:
# 数学类,属性:pi 功能:求两数和,求一个圆的面积


# class Circle:
#     def __init__(self, r):
#         self.r = r
#
#     def area(self, pi):
#         return pi*self.r**2
#
#
# class MyMath:
#     pi = 3.1415926
#
#     @staticmethod
#     def sum1(n1, n2):
#         return n1 + n2
#
#     @classmethod
#     def circle_area(cls, other):
#         return other.area(cls.pi)


class MyMath:
    pi = 3.1415926

    @staticmethod
    def sum1(n1, n2):
        return n1 + n2

    @classmethod
    def circle_area(cls, r):
        return cls.pi*r**2


print(MyMath.sum1(1, 4))        # 5
print(MyMath.circle_area(4))    # 50.2654816

14.2 私有化

  • 1.私有化
    在类中,可以通过在属性名或方法名前加_(注意:不能以_结尾),那么这个属性或方法会变成私有的,那么私有的属性和方法都不能在外部使用。
class Person:
    num = 100
    __num = 200    # 私有属性
    __num__ = 300  # 不是私有属性

    def __init__(self):
        self.name = 1

    def show_name(self):
        print('内部使用:', Person.__num)
        print(self.name)


p1 = Person()
print(Person.num)
# print(Person.__num)
# AttributeError: type object 'Person' has no attribute '__num'
print(p1.show_name())
  • 2.私有化原理
    python中没有真正的私有化,不能从访问权限上控制属性和方法的使用,只是在名字前
    有_但是没有以_结尾的名字前再加了一个'_类名',导致不能通过原属性和方法名进行访问。

14.3 对象属性的getter和setter

  • 1.getter和setter
    如果希望在获取对象属性前做点别的事情,就给这个属性添加getter;
    如果希望给对象赋值前做点别的事情,就给这个属性添加setter

  • 2.添加getter
    a.属性命名时属性名前加一个下划线(_属性名)如:self._age = 0
    b.声明一个函数,函数名是属性名(不要下划线),不需要额外参数;并且函数前使用@property修饰,这个函数的返回值就是获取属性的结果。
    c.当需要获取属性时,通过 对象.一个不带下划线的属性,如:对象.age

@property
def age(self):
    return 年龄相关值
  • 3.给对象属性添加setter
    想要给对象属性添加setter,必须先给它添加getter
    a.属性命名时属性名前加一个下划线(_属性名)如:self._age = 0
    b.声明一个函数,函数名是属性名(不要下划线),需要一个额外的参数;不用返回值,并且函数前使用@getter名.setter来修饰
    c.当需要给属性赋值时,通过 对象.不带下划线的属性来赋值;如:对象.age = 100
    例如:
@age.setter
def age(self, age):
    其它操作
    self._age = age
class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age
        self.sex = '男'

    # 这儿的age属性就是属性__age的getter方法。
    @property
    def age(self):
        if self._age < 1:
            return '婴儿'
        elif self._age < 18:
            return '未成年'
        else:
            return 'LOL'

    # 这儿的age函数就是属性_age的setter
    @age.setter
    def age(self, age):
        if not isinstance(age, int):
            print('年龄必须是整数!')
            raise ValueError
        if not 0 <= age <= 100:
            print('年龄超出范围')
            raise ValueError
        self._age = age


p1 = Person('666', 100)
p2 = Person('666', 16)
# print(p1.age)       # 希望取到的不是年龄,而是年龄对应的阶段
# p1.age = -12        # 存0
# p1.age = 200        # 存150

# 这儿实质是在调用__age的getter方法。
print(p1.age)         # LOL
print(p2.age)         # 未成年

# 这儿实质是在调用_age的setter方法
p1.age = 88
print(p1.age)         # LOL

# p1.age = 888
# print(p1.age)         # 年龄超出范围


# 练习:声明一个时间类,有一个属性以秒的形式保存时间
# 不断的输入时间:以'xx:xx'分秒的形式输入。并且将这些时间对象保存到列表中,直到
# 输入end,为止。 10:20 --> time.秒 = 620


class Time:
    # time_list = []

    def __init__(self, str1:str):
        self._str1 = str1

    @property
    def str1(self):
        list1 = self._str1.split(':')
        second = int(list1[0])*60 + int(list1[1])
        # Time.time_list.append(second)
        return second

    @str1.setter
    def str1(self, str1):
        self._str1 = str1

    """
    补充:打印自己声明的类的对象时,默认打印的是:<模块名.类名 object at 对象地址>
    如果不希望以默认方式打印对象,可以用以下魔法方法实现。打印对象时,就会打印这个
    魔法方法的返回值,必须是字符串。
    """
    # def __repr__(self):
    #     return '转换后为:' + str(self.str1)
    def __repr__(self):
        return '>>' + self.__class__.__module__ + self.__class__.__name__ + \
 ' object at ' + hex(id(self)) + '<<'


time_list = []
t1 = Time('10:20')
print(t1.str1)

t1.str1 = '1:20'      # 620
print(t1.str1)        # 80

while True:
    value = input('时间:')
    if value == 'end':
        break
    else:
        t = Time(value)
        time_list.append(t)

print(time_list)

14.4 类的继承

  • 1.继承
    pyhon中类支持继承,并且支持多继承。
    python中类默认情况下是继承自object(object是pyhon中所有类的基类。)

a.什么是继承
一个类可以继承另外一个类,继承者叫子类,被继承者叫父类。继承就是让子类直接拥
有父类中的内容。

b.可以继承哪些内容
所有的属性和方法都可以继承
1.对象属性
2.类的字段
3.对象方法
4.类方法
...

class Person:
   num = 61
   # 注意:__slots__对应的值不会被继承
   __slots__ = ('name', 'age', 'sex')
   __num = 16

   def __init__(self, sex):
       self.name = '119'
       self.age = 0
       self.sex = sex

   def show_message(self):
       print('%s你是119吗' % self.name)


# Student类继承Person类
class Student(Person):
   pass


s1 = Student('男')
print(s1.name)            # 119
print(Student.num)        # 61
s1.show_message()         # 119你是119吗

14.5 添加属性和方法

子类除了拥有从父类继承下来的属性和方法,还拥有属于自己的属性和方法

  • 1.在子类中添加方法

a.添加一个新的方法
直接在子类中声明其他方法;添加后子类可以调用自己的方法,也可以调用父类的方法,但是父类不能调用子类的方法。

b.重写父类的方法:重新实现父类方法
完全重写 - 覆盖父类功能 - 直接在子类中重写父类方法
部分重写 - 保留父类功能,添加新的功能 - 在子类中实现父类方法时,通过super()去调用父类方法,再添加新功能。

注意:可以在子类方法中通过super()去调用父类对象方法。
注意:子类静态方法中不能使用此方法,会报错:没有参数,静态方法是没有默认参数self的。
super(类,对象) - 获取对象中父类的部分(要求对象是这个指定类的对象)

c.类中方法的调用过程
通过对象调用方法时,先看当前类中是否声明过此方法,如果声明过就直接调用当前类对应的方法。
如果当前类中没有声明过,会去找父类中有没有声明过此方法,声明过就调用父类方法。
如果父类也没有声明,就去找父类的父类。。以此类推,直到object中也没有,程序崩溃。

class Person:
    num = 61

    def __init__(self, sex):
        self.name = '119'
        self.age = 0
        self.sex = sex

    def show_message(self):
        print('%s你是119吗' % self.name)

    @staticmethod
    def info():
        print('我是人类。')


class Student(Person):

    def study(self):
        print('%s在学习' % self.name)

    # 完全重写
    @classmethod
    def message(cls):
        print('我是学生。')

    @staticmethod
    def info():
        print('我是学生。')

    # 保留父类功能
    def show_message(self):
        super().show_message()
        print('我去上小学')


s1 = Student('男')
p1 = Person('女')

# p1.study()  AttributeError: 'Person' object has no attribute 'study'

Student.info()   # 我是学生。
Person.info()    # 我是人类。

s1.show_message()  # 119你是119吗  我去上小学
p1.show_message()  # 119你是119吗

14.6 添加属性

  • 1.添加类的字段
    直接在子类中添加新的字段

  • 2.添加对象属性
    子类的对象属性是通过继承父类对象属性init方法来的

如果想要在保留父类继承下来的对象属性的前提下,添加新的对象属性,需要在子类init方法中,通过super()去调用父类的init方法。

class Person:
    num = 61

    def __init__(self, sex):
        self.name = '119'
        self.age = 0
        self.sex = sex

    def show_message(self):
        print('%s你是119吗' % self.name)

    @staticmethod
    def info():
        print('我是人类。')


class Student(Person):
    number = 100

    def __init__(self, sex):     # 注意此处父类参数。
        super().__init__(sex)
        self.study_id = 9999

    def study(self):
        print('%s在学习' % self.name)

    # 完全重写
    @classmethod
    def message(cls):
        print('我是学生。')

    @staticmethod
    def info():
        print('我是学生。')

    # 保留父类功能
    def show_message(self):
        super().show_message()
        print('我去上小学')


print(Student.num, Student.number)        # 61 100


# 练习:动物类,有属性:年龄,颜色,类型。要求创建动物对象时,类型和颜色必需赋值
# 年龄可以赋值,可以不赋值
# 声明一个猫类,有属性:年龄,颜色,类型,爱好
# 要求创建猫对象时,颜色必须赋值,年龄,爱好可以赋值,可以不赋值,类型不能赋值。


class Animal:
    def __init__(self,  color, type1, age=99):
        self.type1 = type1
        self.color = color
        self.age = age


class Cat(Animal):
    def __init__(self, color, age=99, like='eat'):
        super().__init__(color, 'cat', age)
        self.like = like


an1 = Animal('犬科', '白色')

cat1 = Cat('黑色')
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容