自学Python之面向对象编程

今天学了Python中面向对象的知识——类

感觉与Java的很相似但也有不同之处。比如Java中只有静态的属性才能直接用类名访问,非静态属性必须用实例来访问;而Python中,在类中定义的属性是类的属性,直接用类名访问。而__init__初始化的属性是实例的属性。其次Java中的继承和多态是不同的,继承只能单继承,多态可以继承多个类的方法;而Python中继承可以是单继承,只需要在定义子类的时候传入多个父类参数即可。

一、类和对象

1. 类的定义

  类名、方法名和属性名的命名:类名首字母大写;方法名和属性名小写,单词之间可用_分割;私有属性以双下划线开头+小写字母,如__age。

  定义类时,如果要继承其他类,在类名后的参数中传入要继承的类即可,如Student(object)就表示Student是object的子类,每个类都是object类的子类(关于继承,下面会详细讲解)。

  类中方法的第一参数必须是实例变量self,而且调用时不需要传入self,这是与普通方法唯一不同之处。

  __init__()方法是在创建实例时调用的,用于对类的实例进行初始化。而该方法的第一个参数必须是self,其他需要绑定的属性在self之后作为参数传入,然后绑定到self,如 self.name = name(self是指实例本身)。

class Student(object):  
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def stuInfo(self):
        print("name: "+self.name+",age: "+str(self.age))

 2. 对象

  类是抽象的,实例是根据类创建的具体对象,创建实例可通过 类名() 的形式,如 Student('amy',20),必须传入与__init__方法匹配的参数,但self不需要传,Python解释器会把实例变量self传进去。

  创建实例后就可以通过 object.attribute 的形式调用其属性和方法,如下:

s = Student('amy',20) #创建类的实例
print(s.name) #调用属性
print(s.age)
s.stuInfo()    #调用方法

  结果为:

  

 

 二、访问控制

  类中的属性或方法如果是公共的,则所有实例都可以访问并修改,会带来一定的安全问题。为了防止随笔修改,或者不想被外部变量访问,可以定义为私有属性和方法。

  私有变量的定义:以双下划线开始,如__age,定义为私有变量后,调用时会抛出异常,如下:

class Student(object):  
    def __init__(self,name,age):
        self.__name = name
        self.__age = age

    def stuInfo(self):
        print("name: "+self.__name+",age: "+str(self.__age))

  再次调用:

s = Student('amy',20)
print(s.name)

  结果为:

  

  调用公共的stuInfo方法:

s = Student('amy',20)
s.stuInfo()

  结果:

  

  可见,私有变量不能直接被实例对象访问,若要使用,可通过公共方法。

 

三、继承

1. 我的理解

  Python中子类继承父类时,直接定义子类的时候,传入父类名即可。

  父类:

class Animal(object):
    def run(self):
        print('Animal is running...')    

  子类:

class Dog(Animal):  #传入父类名作为参数
    pass

class Cat(Animal):
    pass

  和其他语言一样,子类继承父类后可直接使用父类中的方法。

  子类也可以对继承自父类的方法进行修改,此时会覆盖父类的该方法,子类的实例在调用改方法时,执行的是子类的特有功能。

  如下,在Cat类中的定义自己的run()方法

class Cat(Animal):
    def run(self):
        print('Cat is running...')  

  两个子类的实例调用run()方法:

dog = Dog()
cat = Cat()
dog.run()
cat.run()

  结果为:

  

  此外,Python支持多重继承,即一个子类可以同时继承多个父类,获得多个父类的方法,只要在定义子类时传入多个父类名即可。
  如下,表示Dog类继承了Mammal类和 Runnable类,可同时获得这两个父类的方法:

class Dog(Mammal, Runnable):
    Pass

   还可以一层层的不断地继承,这样就形成了继承树。在继承树种,子类可获得其上所有父类的方法,如下:

  

 

2. 其他

  http://www.cnblogs.com/superxuezhazha/p/5737955.html 在学习的过程中,看到了这边博客,觉得博主写的挺不错的,在此转载一下。

 

四、类属性和实例属性

1. 概念

  类属性即在类中定义、属于类的属性,实例属性则是属于类的实例的属性,是在创建类的实例时绑定的属性。

  类属性可以通过类直接访问,也可以通过类的属性访问;而实例属性只能通过类的实例访问。

  在一个类中,如果类属性和实例属性同名,通过实例访问时,获取到的是实例属性的值,就是说实例属性覆盖了类属性;而直接通过类名获得的一定是类属性的值。

2. 举例

class Student(object):
    name = 'class'
    def __init__(self, name):
        self.name = name

s = Student('obj')
print(Student.name) #类属性
print(s.name) #实例属性

  结果为:

  

 

五、获取对象信息

1. type()

  用于返回对象类型,特定情况下可通过判断类型是否与期望一致,再继续后续操作。

  可用于基本数据类型、引用类型和自定义类型等,具体如下:

import math
import types
import sys

class Student():
    pass

def fn():
    pass

def test():
    print(type(123))
    print(type('str'))
    print(type(12.34))
    print(type(None))
    print(type([1,2,3]))
    print(type((123,456)))
    print(type({'key':'value'}))
    print(type(math))
    print(type(Student))
    print(type(fn))
    print(type(abs))
    print(type(123) == type(456))
    print(type('abc') == str)
    print(type(fn) == types.FunctionType)
    print(type(abs)==types.BuiltinFunctionType)
    print(type(lambda x: x)==types.LambdaType)


test()

  结果:

  

2. isinstance()

  用于判断一个对象是否属于一个类型。

  用于基本类型,如下:

def test():
    print(isinstance('abc', str))
    print(isinstance(123, int))
    print(isinstance([1,2,3], list))

test()

   结果:

   

  用于自定义类和其对象、子类对象和父类的类型判断:

class Animal(object):
    def run(self):
        print('Animal is running...')    
class Dog(Animal):  
    pass

class Cat(Animal):
    pass

def test():
    dog = Dog()
    cat = Cat()
    print(isinstance(dog,Dog))
    print(isinstance(cat,Cat))
    print(isinstance(dog,Animal))
    print(isinstance(cat,Animal))

test()

  结果:

  

3. dir()

  用于获得一个对象的所有属性和方法,它返回一个包含字符串的list,如下:

  

  __xxx__的属性和方法是有特殊用途的,其余表都是普通方法。比如__len__方法返回长度。在Python中,如果调用len()函数获取一个对象的长度,实际上,在len()函数内部,会自动去调用该对象的__len__()方法,即:

  len('abc') 等价于 'abc'.__len__()。

  此外,hasattr()、getattr()和setattr() 可用来操作对象上的属性

class Student(object):  
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def stuInfo(self):
        print("name: "+self.name+",age: "+str(self.age))

def test():
    s = Student('Amy',20)
    print(hasattr(s,'name')) #判断对象s是否有name属性
    print(hasattr(s,'age'))
    print(hasattr(s,'gender'))
    print(getattr(s,'name')) #获得对象s的name属性值
    print(getattr(s,'age'))
    print(getattr(s,'gender','404')) #获得对象s的gender属性值,不存在时返回404
    setattr(s,'name','Bob') #设置对象s的name属性值
    print(s.name)
    setattr(s,'age',22)
    print(s.age)
    setattr(s,'gender','femal')
    print(s.gender)

test()

  结果:

  

 

posted @ 2017-09-08 14:32  wy820  阅读(326)  评论(0)    收藏  举报