Python每日笔记09(面向对象)

本次内容:面向对象
大量高能预警

>> Python每日笔记—目录 <<

面向对象:

面向对象技术简介:
(Class):用来描述具有相同属性的方法的对象的集合
对象:是类的实例
方法(function):类中定义的具有一定功能的函数。
类变量:类变量在整个实例化的过程当中是共用的。类变量定义在类中,且在函数体的外面。
类变量通常被实例变量使用。
数据成员:类变量或者实例变量用于处理类及其相关对象的数据。
重写方法:重写同名的方法
局部变量:方法内的变量
实例变量:在类的声明中,属性用变量来表示,称为实例变量。实例变量就是一个用self修饰的变量
继承:一个派生类(子类)继承一个积累(父类),可以继承父类的属性和方法。继承允许吧一个紫烈的对象
作为一个父类的对象对待。(允许多继承的存在,一个类可以继承多个父类)
实例化:创建一个类的实例,具体的类的对象
对象:通过类定义的结构的实例。对象包括两个数据成员:类变量和实例变量、方法
私有属性
__private_attrs:两个下划线开头,声明该属性为私有,必能在类的外部所需使用或直接访问
在类的内部时候访问:self.__private__attrs

**类的专有方法**:
    __init__():构造方法,在生成对象的时候调用
    __del__():析构函数,释放对象的时候调用
    __repr__():打印,转换
    __setitem__():按照索引赋值
    __getitem__():根据索引取值
    __add__():加运算
    __sub__():减运算
    __mul__():乘运算
    __div__():除运算
    __mod__():求余数运算
    __pow__():次方运算

self 和 构造方法

  1. self等同于Java和C++中的this关键字,self代表类的实例(当前对象),而不是类,但是self不是关键字,也就是说在参数列表中可以自己命名self。
  2. 类方法和普通方法的区别:类方法里有额外参数self
  3. 构造方法__init__: 和java中类的构造方法一样,用于初始化对象,可以设置参数
class MyClass:
    i = 1000
    '''类的介绍,简单类的实例'''
    def f(self):    # self(自身)自动生成,且调用时不需要参数
                    # 默认的是self,可以修改
        return "Hello,world"
    # 和java中类的构造方法一样,用于初始化对象
    def __init__(self):
        print("这是构造方法")
  
if __name__ == '__main__':
    '''创建一个类的实例'''
    x = MyClass()   # print"这是构造方法"
    # 通过该MyClass的对象访问属性
    print(x.i)  # 1000
    # 通过该MyClass的对象访问方法
    print(x.f())  # Hello,world

私有属性 和 继承关系

  1. 私有属性就是在属性名前面加双下划线__,私有属性同Java中的private一样,不能直接通过对象名访问,需要调用方法访问私有属性。
class people:
    # 定义基础属性
    name = ''
    age = 0
    # 定义私有属性
    __weight = 0

    # 定义构造方法
    def __init__(self, n, a, w):
        self.name = n
        self.age = a
        self.__weight = w

    def speak(self):
        print("%s说: 我今天%d岁了,体重%dKG" % (self.name, self.age, self.__weight))

'''实例化people,使用实例化对象访问speak函数'''
    P = people("大火", 38, 75)
    P.speak()
    '''私有属性不能直接访问,私有属性要用函数去访问!'''
    # print(P.__weight)
  1. 继承:Python中支持多继承关系,子类可以继承父类中的方法和变量,如下给出一个例子:
class people:
    # 定义基础属性
    name = ''
    age = 0
    # 定义私有属性
    __weight = 0

    # 定义构造方法
    def __init__(self, n, a, w):
        self.name = n
        self.age = a
        self.__weight = w

    def speak(self):
        print("%s说: 我今天%d岁了,体重%dKG" % (self.name, self.age, self.__weight))

class person:
    id = 0
    address = ''
    def __init__(self, id, a):
        self.id = id
        self.address = a
    def speak(self):
        print("这是person中的speak方法")


class student(people, person):  # student作为people的子类继承
    grade = ''
    def __init__(self, n, a, w, g, id, address):
        # 调用父类的构造函数
        people.__init__(self, n, a, w)
        person.__init__(self, id, address)
        self.grade = g

    def speak(self):
        print("%s说: 我今天%d岁了,在读大%d年级" % (self.name, self.age, self.grade))

if __name__ == '__main__':
    '''实例化student对象,并访问speak方法,测试该speak方法是父类还是子类的?	子类,子类中重写的speak的方法'''
    # S = student("小火", 20, 75, 3)
    # S.speak() # 子类的speak方法

    '''多继承传参测试
    	进行这项案例是,需要将student中的speak函数注释掉'''
    S2 = student("小火", 20, 75, 3, 101, "中国")
    S2.speak()  # 小火说: 我今天20岁了,体重75KG
    # 在继承的情况下, 调用父类中重名方法的时候,默认调用的是在继承的括号中靠前的方法
    # 样例中输出了people的speak,但没有输出person的speak
  1. super关键字:
    如果你具有其他对象对象语言的基础,你应该思考,子类如何调用父类的方法或者变量呢? super关键字
class Parent:   # 父类
    def my_method(self):
        print("调用父类的方法")

class Child(Parent):
    def my_method(self):
        print("调用子类的方法")

c = Child()
c.my_method()
# 想用子类对象调用父类中被覆盖的方法
# super()可以调用父类的方法,参数1 = 类名, 参数2 = 对象名
super(Child, c).my_method()

super还可以在函数体内调用父类的方法或者变量:

'''
super()是用于调用父类的一个方法
super()是用来解决多重继承问题,直接用类名调用父类方法使用单继承的时候没有问题
在多继承的情况下,会涉及到查找顺序,还有重复调用等问题
'''
class A:
    def add(self, x):
        y = x + 1
        print(y)

class B(A):
    def add(self,x):
        # 直接使用super相当于调用父类中的方法
        super().add(x)
        # 完整写法
        super(B, self).add(x)
if __name__ == '__main__':
	b = B()
	b.add(4)    # 5
  1. 子类如何调用父类中的构造方法(init)呢?
'''
如果在子类当中需要父类的构造方法,
    1、显示调用 
    2、不重写父类的构造方法
子类不重写__init__,实例化子类的时候,会自动调用父类的__init__方法
'''
class Father(object):
    def __init__(self, name):
        self.name = name
        print('name=%s' % self.name)
    def getName(self):
        print('Father', self.name)

class Son(Father):
    def __init__(self, name):
       # 两种调用父类的构造函数的方法
       super(Son, self).__init__(name)
       # Father.__init__(self, name)
       print("测试")
    def getName(self):
        print('Son', self.name)

if __name__ == '__main__':
    # 测试如何调用父类的方法
    # s = Son()     报错,原因:调用父类的构造函数需要参数
    s = Son('小火')   # name=小火
    # 如果子类没有构造函数,会自动调用父类里的构造函数
  1. 私有方法和私有变量
    私有方法同私有变量的写法一样都是在前面加双下划线__
    在类外部,不能直接访问私有变量
    在类外部,不能直接调用私有方法
    给出一个案例:
class JustCounter:
    __se = 0 # 私有变量
    public = 0

    def count(self):
        self.__se += 1
        self.public += 1
        print(self.__se)

    def __pre(self): # 私有方法
        self.__se += 1
        self.public += 1
        print(self.__se)

just = JustCounter()
just.count()    # 1
# print(just.__se)  在类外部,不能直接访问私有属性
# just.__pre        在类外部,不能直接调用私有方法

  1. 方法的重写
    思考一下,为什么 print(t.sum(2, 3))会报错?
    因为,sum的方法已经被重写,参数个数不一致。
class test:
    def sum(self, num1, num2):
        return num1 + num2
    def sum(self, num1, num2, num3):
        return num1 + num2 + num3

t = test()
# print(t.sum(2, 3))	报错
print(t.sum(2, 3, 4))
  1. 类的方法和静态方法:
    这两个方法极其相似,但仍然有区别:
静态方法类的方法
静态方法装饰器下定义的方法属于函数(function);类方法装饰器下定义的方法属于方法(method);
静态方法无需传入任何参数;类方法传入的第一个参数必须是class本身cls;
使用@classmethod声明使用@staticmethod声明
共同点
静态方法与类方法一旦被调用,内存地址即确定。通过类调用和通过实例化对象调用的结果完全一样。

类方法案例:

'''
需要使用装饰器@classmethod来标识为类的方法
第一个参数必须是类对象,一般以cls作为第一个参数
'''
class Dog(object):
    __tooth = 10
    @classmethod
    def get_tooth(self):
        return 0
    def test(self):
        print("测试")

# 2、创建对象,调用类方法
g = Dog()
result = g.get_tooth()
result = Dog.get_tooth()
# Dog.test()  # 报错
# Dog.test(g) # 不会报错
print(result)

静态方法案例:

'''静态方法
    静态方法使用@staticmethod来修饰,静态方法不需要传递类对象,也不需要传递实例对象(形参self/cls)
    静态方法可以通过实例对象和类对象访问
    减少不必要的内存占用和性能消耗
'''

class test(object):
    @staticmethod
    def info_print():
        print("这是一个静态方法")

t = test()
t.info_print()  # 这是一个静态方法
test.info_print()   # 这是一个静态方法  静态方法可以直接类名访问

单选/多选题(使用继承的方法)

1、输入题目和备选答案
2、预设答案
3、使用前面的可变参数
4、调用对象的方法进行对比

class Select:
    title = ""
    options = ""
    answers = []

    def set_titile(self):
        self.title = input("请输入题干")

    def set_option(self):
        self.options = input("请输入选项")

    def set_answers(self, *answer):
        for i in range(len(answer)):
            self.answers.append(i)

    def check(self, submits):
        for i in range(len(submits)):
            flag = 1
            for j in range(len(self.answers)):
                if submits[i] == self.answers[j]:
                    continue
                else:
                    flag = 0
            if flag == 0:
                return "回答错误"
        else:
            return "回答正确"

    def begin(self):
        print(self.title)
        print(self.options)

class One(Select):
    def set_titile(self):
        super(One, self).set_titile()
    def set_option(self):
        super(One, self).set_option()
    def set_answers(self, *answers):
        super(One, self).set_answers()
    def begin(self):
        super(One, self).begin()

class Two(Select):
    def set_titile(self):
        super(Two, self).set_titile()
    def set_option(self):
        super(Two, self).set_option()
    def set_answers(self, *answers):
        super(Two, self).set_answers()
    def begin(self):
        super(Two, self).begin()

if __name__ == '__main__':
    s = One()
    s.set_titile()
    s.set_option()
    s.set_answers('A')
    s.begin()
    sub = input("请输入答案")
    print(s.check(sub))

    s2 = Two()
    s2.set_titile()
    s2.set_option()
    s2.set_answers('A', 'B')
    s2.begin()
    sub = input("请输入多选答案")
    print(s2.check(sub))

tips: 方法和函数有所不同,方法是对象的函数。

周末休两天,没有内容了周一再更,朋友们可以关注本栏目,持续更新ing

如果这篇文章对你有帮助的话,点个赞呗

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值