[PY3]——面向对象编程(1)

类的对象

有三种对象

可以做什么操作

包括什么属性

类对象

属性引用、实例化

函数方法、内置的属性、类变量

实例对象

属性引用

函数方法、类变量、实例变量

方法对象

 

 

 

1. 类对象、实例对象、方法对象

类[class]是抽象的模型
实例[instance]是根据类创建出来的一个个具体的“对象”

1.1  如何定义类

class 类名(表示该类是从哪个类继承下来的): 
  xxx

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

1.2  属性引用

class Myclass(object):
    '''A simple example about class'''
    i=123
    def f(self):
        return "hello world"
    def __init__(self,name,score):
        self.name=name
        self.score=score

# 引用类变量、方法,都是合理的属性引用,分别返回一个整数和一个函数对象
print(Myclass.i)
123
print(Myclass.f) ->这就叫做创建了方法对象,但要注意这只是创建了对象但不是调用了这个方法
<function Student.f at 0x7f81f42c58c8>

# 类还有内置的属性可以被引用
print(Myclass.__doc__)
A simple example about class
print(Myclass.__name__)
Myclass
print(Myclass.__dict__)
{'__doc__': 'A simple example about class', '__init__': <function Myclass.__init__ at 0x7f0bf8fd0950>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Myclass' objects>, 'i': 123, '__dict__': <attribute '__dict__' of 'Myclass' objects>, 'f': <function Myclass.f at 0x7f0bf8fd08c8>}
print(Myclass.__module__)
__main__
print(Myclass.__bases__)
(<class 'object'>,)
内置类 描述
__dict__ 类的属性
__doc__ 类的文档字符串
__name__ 类名
__module__ 类定义所在的模块
__bases__ 类的所有父类构成元素

1.3 实例化操作

# 实例化操作如下所示,赋值给一个变量,就能够创建一个实例对象
x=Myclass()
y=Myclass()
print(x.i) 
123
print(x.f())
hello world
print(x.__doc__)
A simple example about class

# 创建的实例对象可以自由地绑定属性
x.iii="a9a"
print(x.iii)
a9a
# 创建的每个实例对象的内存地址都不一样
print(x)
<__main__.Myclass object at 0x7fbe7fa53160>
print(y)
<__main__.Myclass object at 0x7fbe7f7a8630>

1.4 __init__

# 上述的实例化操作创建了一个空的object
# 但在很多情况下,我们创建实例对象时,可能都需要有特定的初始状态。这个由__init__方法实现。
# 当一个类定义了 __init__() 方法, 类在实例化时会自动调用 __init__() 方法, 用于创建新的类实例

class Myclass(object): '''A simple example about class''' i=123 def f(self): return "hello world" def __init__(self,name,score): self.name=name self.score=score # 关于__init__,要注意的是:
(1) __init__方法的第一个参数永远是self,表示创建的实例本身

(2) 有了__init__方法,在创建实例时就不能传入空的参数了,必须传入匹配的参数

x=Myclass() TypeError: __init__() missing 2 required positional arguments: 'name' and 'score' x=Myclass("J",11) print(x.name,x.score) J 11

 

2. 属性之“变量属性”、作用域问题、访问限制问题

2.1  类变量、实例变量、作用域

class test:
    x=7                    #类的直接下级作用域的变量,叫做类变量

    def __init__(self,name):
        self.name=name      #实例中的变量,叫实例变量


instance1=test("name1")
instance2=test('name2')

# 类变量:既是类对象可见的属性、也是实例对象可见的属性
print(test.x)
7

print(instance1.x)
7

# 下面的例子中,instance1.x+=100本质是实例对象instance1新建了一个属性,覆盖了instance1.x这个变量
# 我们要知道,类变量可以是类对象的属性也可以是实例对象的属性,但实例对象的属性变化影响不了类对象的属性,也不会影响其他的实例对象
# 反之,类对象属性的变化倒是能影响实例对象的属性
test.x=100
print(instance1.x)
100
print(test.x)
100

instance1.x+=100
print(instance1.x)
107
print(test.x)
100
print(instance2.x)
100

2.2 访问限制

# 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
# 这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮

class Student(object):
    def __init__(self,name,score):
        self.__name=name
        self.__score=score

stu=Student('J',100)
print(stu.__score)
AttributeError: 'Student' object has no attribute '__score'


# 如果要允许外部访问者两个变量,可以增加get方法(get_name()和get_score())
# 如果又要允许外部修改这两个变量,可以增加set_score,虽然显得大费周折,但我们可以顺带对参数做个检查

class Student(object):
    def __init__(self,name,score):
        self.__name=name
        self.__score=score

    def get_name(self):
        return '{}'.format(self.__name)

    def get_score(self):
        return '{}'.format(self.__score)

    def print_stu(self):
        print('%s:%s' % (self.__name,self.__score))

    def set_score(self,score):
        if 0<=score<=100:
            self.__score=score
        else:
            raise ValueError('bad score')


stu=Student('J',100)
print(stu.get_name())
J
print(stu.get_score())
100
stu.print_stu()
J:100

stu.set_score(
99);print(stu.get_score()) 99 stu.set_score(101) ValueError: bad score

 

 3. 父类、子类(继承、多态)

# 基类/父类/超类(base class/super class) <—— 子类(subclass)

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

    def run2(self):
        print("111")

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

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

animal=Animal()
dog=Dog()
cat=Cat()

# 子类父类存在同名方法时,子类方法覆盖父类方法
dog.run()
Dog is running...
dog.run2()
111
cat.run()
Cat is running...

# 可以通过isinstance(obj, class_or_tuple, /),可以判断一个instance object是否属于某个类
print(isinstance(dog,Dog))
True
print(isinstance(dog,Animal))
True
print(isinstance(animal,Dog))
False

# issubclass(cls, class_or_tuple, /)class Base:
    Public_class_var='public class var'     #类变量(public)
    __Private_class_var='private class var' #类变量(private)

    def __init__(self):
        self.public_instance_var='public instance var'     #实例变量(public)
        self.__private_instance_var='private instance var' #实例变量(private)

    def public_instance_method(self):
        return 'public instance method'

    def __private_instance_method(self):
        return 'private instance method'

    @classmethod
    def public_class_method(cls):
        return 'public class method'

    @classmethod
    def __private_class_method(cls):
        return 'private class method'

    @staticmethod
    def public_static_method():
        return 'public static method'

    @staticmethod
    def __private_static_method():
        return 'private static method'

class Sub(Base):
   pass

sub=Sub()
print(sub.__dict__)
{'_Base__private_instance_var': 'private instance var', 'public_instance_var': 'public instance var'}

# 子类可以继承类变量(public)、实例变量(public) class Sub(Base): def print_public_var(self): print(self.Public_class_var) def print_public_instance_var(self): print(self.public_instance_var) sub=Sub() sub.print_public_var() public class var sub.print_public_instance_var() public instance var # 事实上凡是公有的都能继承,凡是私有的都不能继承 class Sub(Base): def print_public_class_method(self): print(self.public_class_method()) def print_public_static_method(self): print(self.public_static_method()) def print_public_instance_method(self): print(self.public_instance_method()) sub=Sub() sub.print_public_class_method() public class method sub.print_public_static_method() public static method sub.print_public_instance_method() public instance method

 

 4. classmethod、staticmethod

class A(object):
    def foo(self,x):
        print("executing foo({},{})".format(self,x))

    @classmethod
    def class_foo(cls,x):
        print("executing class_foo({},{})".format(cls,x))

    @staticmethod
    def static_foo(x):
        print("executing static_foo({})".format(x))

a=A()

a.foo(1)
executing foo(<__main__.A object at 0x7fe8619c7160>,1)

a.class_foo(1)
executing class_foo(<class '__main__.A'>,1)

a.static_foo(1)
executing static_foo(1)

a.static_foo('hi')
executing static_foo(hi)

A.class_foo(1)
executing class_foo(<class '__main__.A'>,1)

A.static_foo(1)
executing static_foo(1)

A.foo(1)TypeError: foo() missing 1 required positional argument: 'x'

print(a.foo)
<bound method A.foo of <__main__.A object at 0x7f57d0ba41d0>>

print(a.class_foo)
<bound method A.class_foo of <class '__main__.A'>>

print(a.static_foo)
<function A.static_foo at 0x7f71b0c89b70>

 

参考文章

《Python3文档——类》

《极客学院——从零开始学python——类(3)》

《廖雪峰——面向对象——访问限制》

posted @ 2017-09-15 17:59  Jelly_lyj  阅读(163)  评论(0编辑  收藏  举报