1. 程式人生 > >單例設計模式、類方法、例項方法、靜態方法、修改類屬性

單例設計模式、類方法、例項方法、靜態方法、修改類屬性

在python2中沒有宣告父類,則沒有父類,
在python3中沒有宣告父類,則父類為object,object為所有類的父類

:   1:例項屬性:

:    最好在__init__(self,…)中初始化

:    內部呼叫時都需要加上self.

:    外部呼叫時用instancename.propertyname

2:類屬性:
  		類屬性:(修改多個物件的某個特徵更加簡單,程式執行中)

:    在__init__()外初始化

:    在內部用classname.類屬性名呼叫

:    外部既可以用classname.類屬性名又可以用instancename.類屬性名來呼叫
   3:私有屬性:

1):單下劃線_開頭:只是告訴別人這是私有屬性,外部依然可以訪問更改

2):雙下劃線__開頭:外部不可通instancename.propertyname來訪問或者更改, (Python不允許例項化的類訪問私有資料,但你可以使用 object._className__attrName 訪問屬性

:    實際將其轉化為了_classname__propertyname

子類繼承父類,繼承了父類的公有方法、屬性
dir(物件名):顯示物件的屬性和方法
dir(str)
dir(dict)
dir(tuple)

# 繼承也能呼叫私有的屬性和方法
class Person
(object): def __init__(self, name, age, money): self.name = name self.age = age self.__money = money def __step(self): print(self) class Women(Person): pass yang = Women('yue', 18, 1000) print(dir(yang)) print(yang._Person__money) yang._Person__step()

2 類屬性的重新賦值(唯一一種方式)

Python的類和類例項都是可變物件,可以隨時給屬性賦值,並且在原處修改。

在對類屬性進行修改時需要特別小心,因為所有的類例項都繼承共享類屬性,除非例項本身存在和類屬性同名的屬性。對類屬性進行修改,會影響到所有由這個類生成的例項。

class Person(object):
    country = 'china'
    pass


print(Person.country)
Person.country = 'yang'
print(Person.country)

修改類屬性

class People(object):
    country = 'china' #類屬性


print(People.country) # 類名呼叫類屬性
p = People()
print(p.country) # 物件對用類屬性
p.country = 'japan'
print(p.country)  # 例項屬性會遮蔽掉同名的類屬性
print(People.country)
del p.country  # 刪除例項屬性
print(p.country)

china
china
japan
china
china
如果需要在類外修改類屬性,必須通過類物件去引用然後進行修改。如果通過例項物件去引用,會產生一個同名的例項屬性,這種方式修改的是例項屬性,不會影響到類屬性,並且之後如果通過例項物件去引用該名稱的屬性,例項屬性會強制遮蔽掉類屬性,即引用的是例項屬性,除非刪除了該例項屬性。

空值型別

# 空值型別
n = None
print(type(n))  # <class 'NoneType'>
print(id(n))  # 10353568 python已經開闢好的空間儲存當前的空值型別
print(None is False)  # False

new

# __new__
#__new__方法才是真正的建構函式。
# 監聽物件建立成功並返回例項物件
def __new__(cls, *args, **kwargs):
    return object.__new__(cls)

# init
# __init__ 方法為初始化方法,
# 監聽物件建立成功後,給物件新增屬性並賦值
# 
# 
# 追蹤通過這個類建立的物件的屬性值變化的
# 監聽記憶體地址的引用計數位0,(呼叫__del__監聽物件銷燬)

例子1:

# 單例設計模式:通過一個類創建出來的所有的物件的地址都是一樣的
# 如果想使用這個類建立的物件代表不同的事物,正常建立即可
# 如果只是想使用類中的方法,不關心物件是不同的物件,可以使用單例模式,(節約記憶體)
class Singleton(object):
    # __country 類變數:可以通過類名、或者物件直接呼叫
    __country = 'china'
    # 定義一個類屬性儲存物件
    instance = None
    #
    __is_first = True

    def __new__(cls, *args, **kwargs):
        # 判斷是否第一次建立物件,如果是則呼叫父類的__new__方法返回例項化出來的例項,
        #  保證只有一個物件
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

    def __init__(self, age, name):
        if self.__is_first:
            self.__name = name
            self.age = age
            self.__is_first = False

    # cls -> class -> Person
    @classmethod    # 修飾器
    def get_country(cls):
        return cls.__country

    def func(self):
        print(self.__name)

    @staticmethod
    def hello():
        print('hello')


a = Singleton(18, 'xizi')
b = Singleton(20, 'xiaojia')
print(id(a) == id(b))  # True   地址一樣,不建立新的物件
print(a.age)
print(b.age)
a.age = 19

print(a.age)
print(Singleton.get_country())  # china
print(a.func())  # 18  \n None, 函式執行完事之後,列印的話為None
print(Singleton)

例二

class HelloWorld():
    def set(self, word):
        self.word = word

    def say_hello(self):
        print(self.word)


class SingleCase(object):

    def __new__(cls, *args, **kwargs):
        if not hasattr(SingleCase, "_instance"):
            cls._instance = super(SingleCase, cls).__new__(cls, *args, **kwargs)
            cls._instance.hello = HelloWorld()
            print("cls._instance.hello", id(cls._instance.hello))
            cls._instance.hello.set("Hello world")
            cls_addr = id(cls._instance)
            print("cls_addr", cls_addr)
        return cls._instance

    def print(self):
        self_addr = id(self)
        instance_addr = id(self._instance)
        print("self_addr", self_addr)
        print("instance_addr", instance_addr)
        self.hello.say_hello()


a = SingleCase()
b = SingleCase()
a.print()
print(id(a))
print(id(b))
"""output
cls._instance.hello 140312550013864
cls_addr 140312550013696
self_addr 140312550013696
instance_addr 140312550013696
Hello world
140312550013696
140312550013696
"""