2009-06-25 30 views
13

Tôi muốn tạo ra một ID duy nhất cho từng đối tượng Tôi tạo ra - đây là lớp:Làm thế nào để bạn tạo ra một ID gia tăng trong một lớp Python

class resource_cl : 
    def __init__(self, Name, Position, Type, Active): 
     self.Name = Name 
     self.Position = Position 
     self.Type = Type 
     self.Active = Active 

Tôi muốn có một self.ID rằng tự động increments everytime tôi tạo ra một tham chiếu mới đến lớp, chẳng hạn như:

resources = [] 
resources.append(resource_cl('Sam Sneed', 'Programmer', 'full time', True)) 

tôi biết tôi có thể tham khảo resource_cl, nhưng tôi không chắc chắn làm thế nào để tiến hành từ đó ...

Trả lời

3

Bạn có biết số id function trong trăn và bạn có thể sử dụng nó thay vì ý tưởng phản đối của mình không?

class C(): pass 

x = C() 
y = C() 
print(id(x), id(y)) #(4400352, 16982704) 
+1

Tôi đã sử dụng id (self) trong lớp - dường như là đúng giải pháp cho nhu cầu của tôi - cảm ơn – meade

+8

Hãy nhớ rằng các giá trị được trả về bởi id() không được đảm bảo là duy nhất trong một lần thực hiện chương trình (chúng có thể được sử dụng lại khi các đối tượng được thu thập). Họ cũng không được bảo đảm tuân theo bất kỳ mẫu cụ thể nào (bạn đã yêu cầu tăng tự động ban đầu). –

+0

R. Pate: hoàn toàn chính xác và quan trọng cần ghi nhớ; Tôi chỉ muốn chắc chắn rằng ông đã nhận thức được sự tồn tại của chức năng id và đánh giá nó đúng cách trước khi chọn làm một cái gì đó bằng tay. – llimllib

12

Thứ nhất, sử dụng chữ hoa Tên cho Classe S. tên thường cho các thuộc tính.

class Resource(object): 
    class_counter= 0 
    def __init__(self, name, position, type, active): 
     self.name = name 
     self.position = position 
     self.type = type 
     self.active = active 
     self.id= Resource.class_counter 
     Resource.class_counter += 1 
+2

Bên trong __init__, tham chiếu class_counter là thuộc tính của lớp. Nó sẽ giống như thế này: Resource.class_counter + = 1 –

+0

S.Lott, tôi đã thử nó. Với phiên bản đầu tiên của bạn, mọi đối tượng sẽ có id là 0 và class_counter là 1. –

+2

sẽ hoạt động trong trường hợp truy cập giá trị. Vì vậy: self.id = self.class_counter Sẽ hoạt động như mong muốn vì độ phân giải thuộc tính sẽ giảm về thuộc tính lớp. Đây không phải là trường hợp thiết lập thuộc tính vì tập giá trị sẽ nằm trong phạm vi của cá thể chứ không phải lớp cơ bản. –

10

Sử dụng đếm từ itertools là rất tốt cho việc này:

>>> import itertools 
>>> counter = itertools.count() 
>>> a = next(counter) 
>>> print a 
0 
>>> print next(counter) 
1 
>>> print next(counter) 
2 
>>> class A(object): 
... id_generator = itertools.count(100) # first generated is 100 
... def __init__(self): 
...  self.id = next(self.id_generator) 
>>> objs = [A(), A()] 
>>> print objs[0].id, objs[1].id 
100 101 
>>> print next(counter) # each instance is independent 
3 

Giao diện tương tự hoạt động nếu sau này bạn cần phải thay đổi cách các giá trị được tạo ra, bạn chỉ cần thay đổi định nghĩa của id_generator.

38

ngắn gọn và thanh lịch:

import itertools 

class resource_cl(): 
    newid = itertools.count().next 
    def __init__(self): 
     self.id = resource_cl.newid() 
     ... 
+1

+1: Đây là cách đáng tin cậy và an toàn chỉ để thực hiện việc này trong số tất cả các câu trả lời hiện tại. 'id' có thể trả về các giá trị không phải duy nhất, và đơn giản là tăng một biến lớp bên trong' __init__' có thể dẫn đến các điều kiện chủng tộc. Tôi cũng thích ý tưởng lưu trữ một referenec thành 'count(). Next' thay vì lưu trữ trực tiếp kết quả của' count() '. –

+0

Nó xảy ra cùng một đối tượng bằng cách sử dụng id(), ví dụ: a = "123" b = "123" id (a) == id (b) – clsung

+0

@clsung Các chuỗi Python được "interned" và chúng không thể thay đổi được. "123" là cùng một đối tượng thông qua phiên Python của bạn. 'a' và 'b' được đặt tên tham chiếu, không phải là "đối tượng" hoặc "phiên bản" của "123". Trong trường hợp này, họ trỏ đến một chuỗi nội bộ. Google python intern để biết thêm thông tin. – DevPlayer

0

Một lưu ý trên id() và suy nghĩ lại câu trả lời khác về nó. id() có thể trả về một số duy nhất, nếu và chỉ khi nó ghi nhớ mọi id được trả về ngay cả khi một đối tượng bị xóa; mà nó (id()) không làm. Vì vậy, do đó ...

Để hỗ trợ những gì người khác nói rằng id() không trả về một số duy nhất; Đúng là nó không thể guarentee một giá trị duy nhất nếu và chỉ nếu bạn đang lưu trữ những giá trị id() như tham chiếu đến đối tượng VÀ bạn đang xóa các đối tượng của các đối tượng bạn đang nhận id() s cho. NHƯNG ! sử dụng id() làm tham chiếu có nghĩa là bạn về cơ bản có một đối tượng có khóa được liên kết bằng cách nào đó với một đối tượng khác.

Điều này không bị vô hiệu bởi tính không độc đáo của id(). Nó chỉ bị vô hiệu nếu bạn không kiểm tra nếu thêm một đối tượng mới có một id đã tồn tại từ trước() đã được lưu trữ như một tham chiếu đến một số cá thể khác của đối tượng.

storeit = {} 

object1 = object() 
print id(object1) 
4357891223 

storeit[ id(object1) ] = object1 

object2 = object() 
print id(object2) 
9834923411 

storeit[ id(object2) ] = object2 

storeit[ id(object1) ] = object() 
del object1 

object3 = object() 
print id(object3) 
# after some 2 gigawatt tries magically i got 
4357891223 
# the same id as object1 had 

NHƯNG lưu trữ [4357891223] trả về một số đối tượng khác không phản đối3; do đó liên kết <> vẫn hợp lệ nhưng tính duy nhất không thành công.

0

Tôi thích sử dụng trình tạo cho id. Cho phép trình tạo để duy trì danh sách các id đã được sử dụng.

# [email protected] 
# 2012-07(jul)-19 


class MakeUniqueStr(object): 
    ''' 
    unqstr = MakeUniqueStr(default_name='widget', sep='_') 
    print(repr(unqstr('window'))) 
    print(repr(unqstr('window'))) 
    print(repr(unqstr('window'))) 
    print(repr(unqstr('hello'))) 
    print(repr(unqstr('hello'))) 
    print(repr(unqstr('window'))) 
    print(repr(unqstr('hello'))) 

    'window' 
    'window_00000' 
    'window_00001' 
    'hello' 
    'hello_00000' 
    'window_00002' 
    'hello_00001' 
    ''' 

    def __init__(self, default_name='default', sep='_'): 
     self.default_name = default_name 
     self.last_base_name = default_name 
     self.sep = sep 

     self.used_names = [] 

     self.generator = self.Generator() 
     self.generator.next() # initialize 

    def __call__(self, name=None): 
     if name <> None: self.last_base_name = name 
     return self.generator.send(self.last_base_name) 

    def _MakeName(self, name, index=1): 
     '''_MakeName is called by the Generator. 

     Generator will always have a name and an index to pass to _MakeName. 
     Over ride this method to customize it.''' 

     return name + self.sep + '%0.5d' % index 

    def Generator(self): 
     try_name = yield 'ready' # initialize 
     index = 0 
     while 1: 

      if try_name not in self.used_names: 
       self.used_names.append(try_name) 
       sent_name = yield try_name 
       try_name = sent_name 
       continue 

      try_name = self._MakeName(sent_name, index) 
      while try_name in self.used_names: 
       index += 1 
       try_name = self._MakeName(sent_name, index) 

      index = 0 

Mặc dù đây không phải là cách hiệu quả của bộ nhớ trong bộ nhớ lớn trong bộ nhớ. Nếu bạn muốn sử dụng một cái gì đó như thế thì sửa đổi điều này để có hệ điều hành xử lý bộ nhớ đệm vào một tập tin ... nói qua một đường ống có tên.

1

Id đôi khi được hưởng lợi từ việc sử dụng một số trường của đối tượng bạn muốn tham chiếu. Đây là một kỹ thuật cơ sở dữ liệu kiểu cũ.

ví dụ nếu bạn có một ứng dụng mà giữ hồ sơ cho các cuộc gọi điện thoại của khách hàng gửi đến, sau đó sử dụng tốt một id được tạo ra bởi thời gian = một số điều khác

ident = '%s:%.4s:%.9s' % (time.time(), time.clock(), agent.name) 
# don't forget to time.clock() once to initialize it 

chỉ beaware các time.time() và thời gian. clock() là giá trị trả về của máy tính cá nhân trừ khi được tạo trên máy chủ. Và nếu trên máy chủ đảm bảo đồng hồ máy chủ của bạn được đặt đúng; như mọi khi.

Các vấn đề liên quan