Python随笔10

面向对象最重要的是类和实例,类是抽象的,是具有某些相同属性和方法的集合;实例就是根据类创建出来的一个个对象

对象=属性+方法

类的定义:

class 类名(object) :

  语句

其中object是指类继承与哪个类,(object)可不写,所有的类都继承与object类

 

self参数:

  类中的方法无论是有参还是无参,默认都有第一个参数self,称为实例的引用,它也是方法和函数的区别(除此之外没有任何区别)。这个self参数,你可以将其命名为任意参数,但是最好是默认为self。它相当于Java中的this,在你将类实例化之后赋予一个对象,self参数就是这个对象本身。比如你有一个类Class和这个类的一个实例MyClass,当你调用这个对象的方法MyClass.getName(arg1,arg2)时,其实就是相当于MyClass.getName(MyClass,arg1,arg2)

init方法:

  在类的一个对象被创建时,会立即运行一个初始化方法init方法,这个方法就相当于Java中的构造函数。在定义时需要注意init前后各有两条下划线__init()__,定义的时候第一个参数还是self。有init方法的类在创建实例化对象的时候必须给它传入和init方法中相匹配的参数,否则函数会报错。子类不能重写父类的构造方法,如果子类的构造方法中用到了父类的构造方法里面的属性,应该考虑继承。

 

类的实例化:

  一个类Person()创建之后就会产生一个类对象,通过p = Person()可以创建一个Person类的实例。可以直接通过p来调用类的方法和属性(私有属性不能直接调用)。如果Person类有构造方法,在创建类的实例时,需传入对应的参数。

 

 类的私有属性:

  类的私有属性一般用两个下划线表示__i,类的实例不能直接访问,需要通过一些方法去访问和处理这些私有属性。这种方式保证了代码的将壮性。

  访问类的私有变量: 

class Person():
    def __init__(self,name,age):
        self.__name =name
        self.__age = age
    def getName(self):
        return self.__name
    def getAge(self):
        return self.__age
    def setName(self,name):
        self.__name = name
    def setAge(self,age):
        self.__age = age

p = Person("Tom",18)
print(p.__name)
print(p.__age)

  这段代码中Person类中的__name和__age属性都是私有属性,如果想直接访问这里面的属性,p.__name和p.__age,会报错

Traceback (most recent call last):
  File "D:/PythonDemo/hello.py", line 171, in <module>
    print(p.__name)
AttributeError: 'Person' object has no attribute '__name'

  这是因为,Python将私有变量变为了,_Person__name和_Person__age,但是不要用p._Person__name这样的方式去直接访问私有变量,因为不同版本的解释器会把__name变为不同的变量名。需要写一些方法去访问和改变私有变量。上面代码中的getName()、getAge()、setName()、setAge()方法,是用来访问和改变这些私有变量的。

p = Person("Tom",18)
print(p.getAge())
print(p.getName())
p.setName("Jerry")
print(p.getName())
p.setAge(22)
print(p.getAge())

  结果为:

18
Tom
Jerry
22

 

封装、继承和多态:

  类的属性和方法都是放在内部的,我们直接可以在外部使用这些方法去访问类的内部数据,不需要在外面重新写方法,也不需要知道实现的细节,这就叫封装,封装还有一个好处就是可以增加类的方法,比如getAge(),外部同样不用知道方法的细节,但是可以去访问类的数据。

  继承:当我们定义一个类时,可以从某个类继承,这个被继承的类叫做父类(SupperClass或者BaseClass)、新类叫做子类(SubClass),所有的类都继承于Object类。比方说定义一个Man()类继承于Person()类,写法应该是class Man(Person):      子类可以继承父类的方法和属性,比如Person类中有eat()方法,则Man()类中不必再写eat()方法,可以直接使用eat()方法,同样,子类也可以重写父类的方法,在子类的实例调用这个方法时,总是会调用子类的方法。

class Person():
    def __init__(self,name,age):
        self.name =name
        self.age = age
    def eat(self):
        return "i can eat"

class Man(Person):
    pass

m = Man("Tom",12)
print(m.name)
print(m.age)
print(m.eat())

  输出为:

Tom
12
i can eat

  可以看到子类能直接使用类的属性和方法

  再来看子类重写父类的方法“

  

class Person():
    def __init__(self,name,age):
        self.name =name
        self.age = age
    def eat(self):
        return "i can eat"

class Man(Person):
    def eat(self):
        return "i eat more"

m = Man("Tom",12)
print(m.name)
print(m.age)
print(m.eat())

  输出为:

Tom
12
i eat more

  可以看到,调用的是子类的方法

  如果一个类同时继承多个类,从左到右依次继承,对于继承的方法,也是从左到右依次查找,调用先查找到的方法。比如:

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岁,体重是%d公斤" % (self.name,self.age,self.__weight))


class Student(People):
    grade = 0

    def __init__(self, n, a, w, g):
        People.__init__(self, n, a, w)
        self.grade = g

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


class Speaker:
    topic = ""
    name = ""

    def __init__(self, n, t):
        self.name = n
        self.topic = t

    def speak(self):
        print("%s说,我今天演讲的主题是%s" % (self.name, self.topic))


class Sample(Speaker, Student):
    a = ""

    def __init__(self, n, a, w, g, t):
        Student.__init__(self, n, a, w, g)
        Speaker.__init__(self, n, t)

test = Sample("小明", 20, 55, 3, "Python")
print(test.speak())

  Sample(Speaker,Student)类继承于Speaker()和Student(),那么输出的结果为:

小明说,我今天演讲的主题是Python

  如果把继承的顺序变为Sample(Student,Speaker),那么输出的结果为:

小明说:我今年20岁,读3年级

  同时从”People.__init__(self, n, a, w)“也可以看出,子类在写构造方法时,可以直接使用父类.__init__(self,arg1,arg2...)的方式继承父类的构造方法里的属性

 

  多态:Python本身就是一种多态类的语言,如果某些类具有相同的方法,我们可以把它们看作同一类型的。如果Cat类和Dog类都继承于Animal类,它们都有behaviour()方法。我们可以把Animal、Cat、Dog看成Animal、Cat、Dog类型的数据,同时Cat和Dog也是Animal类型的数据,但是反过来就不成立了。我们写一个函数叫做beh,有方法behaviour(),参数类型为Animal类型,这样我们就可以往里面传入Animal、Cat和Dog类型的参数,同时如果我们新建一个类Bird(Animal)继承于Animal,也不必修改beh函数。

class Animal:
    def behaviour(self):
        print("Animal can run")

class Cat(Animal):
    def behaviour(self):
        print("Cat can miaomiaomiao")

class Dog(Animal):
    def behaviour(self):
        print("Dog can wangwangwang")

lst = [Animal(),Cat(),Dog()]
for items in lst:
        print(items.behaviour())
print("===============================")
def beh(animal):
    animal.behaviour()
print(beh(Animal()))
print(beh(Cat()))
print(beh(Dog()))

  结果为:

Animal can run
None
Cat can miaomiaomiao
None
Dog can wangwangwang
None
===============================
Animal can run
None
Cat can miaomiaomiao
None
Dog can wangwangwang
None

  我们只需关注,这个这个参数是Animal类型的就行了,至于具体的是属于Cat类型还是属于Dog类型,则需要看传入的参数是什么,而且当我们新增一个类Bird继承于Animal时,不需要去修改这个函数,只需要保证这个函数的正确性即可,这个就是多态便利性的一个体现。

 

 
 

 

  

转载于:https://www.cnblogs.com/bigbigtong/p/10089235.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值