首页 > 代码库 > 面向对象,类

面向对象,类

1、面向对象

2、类,实例

把一个抽象的类的变成一个具体的对象的过程叫实例化,实例化时,python把实例本身传入类的函数中, 类中__init__函数时初始化函数(方法),实例化时,__init__方法自动执行

 

类本身也是一个内存对象

 

class student(obect):
    school = "middle school"    # 类变量,在类的内存中

    def __init__(self,name,age,sex,major):  #初始化
        self.name = name   # 成员属性或者成员变量,实例化后,在实例的内存空间中
        self.age = age
        self.sex = sex
        self.major = major
  def print_score(self,score): # 类的方法
      self.core = score
      print (self.core)

st1
= student("px",19,"""计算机") st2 = student("pz",18,"","英语")

print  (student.school)

print (st1.school)

print (st2.school)

 

结果为:

middle school

middle school

middle school

 

 

实例可以访问类变量,如果实例有和类相同名的变量,实例访问该变量时,该变量的值为实例变量的值,如果实例没有该变量,则为类变量的值。实例变量不能被类访问调用。

类变量,类属性

成员变量,实例变量

 

 

3、类的三大特性:

 


封装:

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,
对不可信的进行信息隐藏。

多态:


封装和继承都实现了代码重用

多态实现了接口重用,接口统一,

但python没有多态的语法,可以通过一些技巧实现多态的效果:

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


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

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

 

 

def run_twice(animal):
  animal.run()
  animal.run()

 


这样调用run_twice函数时,只要传入的实例是Animal类或Animal子类,都会自动调用实际类型的run方

调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管
原来的代码是如何调用的。这就是著名的“开闭”原则:

对扩展开放:允许新增Animal子类;

对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

 

 

继承:

class SchoolMember(object):
    members = 0 #初始学校人数为0
    def __init__(self,name,age):
        self.name = name
        self.age = age
 
    def  tell(self):
        pass
 
    def enroll(self):
        ‘‘‘注册‘‘‘
        SchoolMember.members +=1
        print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " %(self.name,SchoolMember.members))
     
    def __del__(self):
        ‘‘‘析构方法‘‘‘
        print("\033[31;1mmember [%s] is dead!\033[0m" %self.name)
class Teacher(SchoolMember):
    def __init__(self,name,age,course,salary):
        super(Teacher,self).__init__(name,age)
        self.course = course
        self.salary = salary
        self.enroll()
 
 
    def teaching(self):
        ‘‘‘讲课方法‘‘‘
        print("Teacher [%s] is teaching [%s] for class [%s]" %(self.name,self.course,s12))
 
    def tell(self):
        ‘‘‘自我介绍方法‘‘‘
        msg = ‘‘‘Hi, my name is [%s], works for [%s] as a [%s] teacher !‘‘‘ %(self.name,Oldboy, self.course)
        print(msg)
 
class Student(SchoolMember):
    def __init__(self, name,age,grade,sid):                #重写父类的__init__方法
        super(Student,self).__init__(name,age)              # 同时也继承了父类的_init__方法
        self.grade = grade
        self.sid = sid
        self.enroll()
 
 
    def tell(self):
        ‘‘‘自我介绍方法‘‘‘
        msg = ‘‘‘Hi, my name is [%s], I‘m studying [%s] in [%s]!‘‘‘ %(self.name, self.grade,Oldboy)
        print(msg)
 
if __name__ == __main__:
    t1 = Teacher("Alex",22,Python,20000)
    t2 = Teacher("TengLan",29,Linux,3000)
 
    s1 = Student("Qinghua", 24,"Python S12",1483)
    s2 = Student("SanJiang", 26,"Python S12",1484)
 
    t1.teaching()
    t2.teaching()
    t1.tell()

 

python面向对象的高级语法:

在类中可以用装饰器:

1.在类的某个方法之前加了@classmethod后

该方法将会变成类方法,在该方法内部不能访问实例变量


2.在类的某个方法之前加了@staticmethod后

该方法将会变成类静态方法,在该方法内部不能访问实例和类变量

 

大多数情况没有用,可以使用该类型方法作为类的工具箱


3.在类的某个方法之前加了@property后

该方法将会变成类静态属性,实例只能通过访问属性(变量)的方式访问调用该方法

 

 

私有属性:隐藏变量,
不容许在类的外部访问属性(变量),只容许在类内部访问

self.__name = name (加2个下划线就可以变成私有属性)


但是还是有方法可以在外部访问到私有变量的。
d = Animal("Sanjiang")

print (d._Animal__num)

 

 

类的特殊成员方法:

1、__doc__

表示类的描述信息
class Foo:
  """ 描述类信息"""

  def func(self):
    pass

print Foo.__doc__

#输出:描述类信息

 

2、__module__ 和__class__

分别表示
表示当前操作的对象在哪个模块
表示当前操作的对象属于哪个类


from lib.aa import C

obj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类


3 __init__
构造方法,通过类创建对象时,自动触发执行。

4、__del__

对象在内存中销毁后,自动执行程序该方法


5 __call__
class role(object):
  def __init__(self):
    print (‘__init__‘)

  def __call__(self):
    print (‘__call__‘)

a = role()
a() # 执行__call__ 方法


6 __new__

是它调用执行__init__


7、__dict__

 

查看类或对象中的所有成员

 

8、__str__

如果有定义该方法打印 对象 时,默认输出该方法的返回值。

 

class Foo:
 
    def __str__(self):
        return ‘pengxuan
 
 
obj = Foo()
print obj
# 输出:pengxuan

 

 

 

新式类与经典类:

 

1、区别一:写法不同

 

经典类就是老写法

比如以前类的定义类的写法是这样的

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

 

而新式类是这样写的

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

 

 


区别二:


多继承有区别

class A:
    def f1(self):
        print (a)

class B(A):
    pass

 


class C(A):
def f1(self):
    print (C)

 

class D(B,C):
    n = 3

 


obj = D()

obj.f1()

         

 


这个例子中如果是广度优先,执行obj.f1()时,从父类查找是否有f1方法的顺序是B->C-A;如果是深度优
先,查找f1方法的顺序是B->A->C。最先在哪个类中找到f1方法,则继承那个类中的f1方法

 

 

 

在低于python3.0的版本

经典类是深度优先

新式类是广度优先

 

到python3.X版本
新式类和经典类都是广度优先

 

 

 

 

反射:

hasattr

getattr

setattr

delattr

 

import sys
class WebServer(object):
    def __init__(self,host,port):    # Constructor of the class
        self.host = host
        self.port = port
    def start(self):
        print("Server is starting...")
    def stop(self):
        print("Server is stopping...")
    def restart(self):
       self.stop()
       self.start()
def test_run(self,name):
    print("running...",name,self.host)
if __name__ == "__main__":
    server = WebServer(localhost,333)
    server2 = WebServer(localhost,333)
    #print(sys.argv[1])
    if hasattr(server,sys.argv[1]):
        func = getattr(server,sys.argv[1]) #获取server.start 内存地址
        func() #server.start()

    #setattr(server,‘run‘,test_run)
    #server.run(server,‘alex‘)
    delattr(WebServer,start)
    print(server.restart())
    #server2.run(server,‘alex‘)

    ‘‘‘cmd_dic = {
        ‘start‘:server.start,
        ‘stop‘:server.stop,
    }‘‘‘
    #if sys.argv[1] == ‘start‘:
    #if sys.argv[1] in cmd_dic:
    #    cmd_dic[sys.argv[1]]()

 

面向对象,类