Вот несколько более сложная версия связанного класса списка, с похожим интерфейсом к типам последовательностей python (т. е. поддерживает индексирование, нарезку, конкатенацию с произвольными последовательностями и т. д.). Он должен иметь O (1) prepend, не копировать данные, если только это не требуется, и может использоваться довольно взаимозаменяемо с кортежами.
Это будет не так просто, как пространство или время, как lisp cons cells, так как классы python, очевидно, немного более тяжелы (вы можете немного улучшить ситуацию с помощью «__slots__ = '_head','_tail'
», чтобы уменьшить использование памяти). Однако он будет иметь желаемые характеристики производительности.
Пример использования:
>>> l = LinkedList([1,2,3,4])
>>> l
LinkedList([1, 2, 3, 4])
>>> l.head, l.tail
(1, LinkedList([2, 3, 4]))
# Prepending is O(1) and can be done with:
LinkedList.cons(0, l)
LinkedList([0, 1, 2, 3, 4])
# Or prepending arbitrary sequences (Still no copy of l performed):
[-1,0] + l
LinkedList([-1, 0, 1, 2, 3, 4])
# Normal list indexing and slice operations can be performed.
# Again, no copy is made unless needed.
>>> l[1], l[-1], l[2:]
(2, 4, LinkedList([3, 4]))
>>> assert l[2:] is l.next.next
# For cases where the slice stops before the end, or uses a
# non-contiguous range, we do need to create a copy. However
# this should be transparent to the user.
>>> LinkedList(range(100))[-10::2]
LinkedList([90, 92, 94, 96, 98])
Реализация:
import itertools
class LinkedList(object):
"""Immutable linked list class."""
def __new__(cls, l=[]):
if isinstance(l, LinkedList): return l # Immutable, so no copy needed.
i = iter(l)
try:
head = i.next()
except StopIteration:
return cls.EmptyList # Return empty list singleton.
tail = LinkedList(i)
obj = super(LinkedList, cls).__new__(cls)
obj._head = head
obj._tail = tail
return obj
@classmethod
def cons(cls, head, tail):
ll = cls([head])
if not isinstance(tail, cls):
tail = cls(tail)
ll._tail = tail
return ll
# head and tail are not modifiable
@property
def head(self): return self._head
@property
def tail(self): return self._tail
def __nonzero__(self): return True
def __len__(self):
return sum(1 for _ in self)
def __add__(self, other):
other = LinkedList(other)
if not self: return other # () + l = l
start=l = LinkedList(iter(self)) # Create copy, as we'll mutate
while l:
if not l._tail: # Last element?
l._tail = other
break
l = l._tail
return start
def __radd__(self, other):
return LinkedList(other) + self
def __iter__(self):
x=self
while x:
yield x.head
x=x.tail
def __getitem__(self, idx):
"""Get item at specified index"""
if isinstance(idx, slice):
# Special case: Avoid constructing a new list, or performing O(n) length
# calculation for slices like l[3:]. Since we're immutable, just return
# the appropriate node. This becomes O(start) rather than O(n).
# We can't do this for more complicated slices however (eg [l:4]
start = idx.start or 0
if (start >= 0) and (idx.stop is None) and (idx.step is None or idx.step == 1):
no_copy_needed=True
else:
length = len(self) # Need to calc length.
start, stop, step = idx.indices(length)
no_copy_needed = (stop == length) and (step == 1)
if no_copy_needed:
l = self
for i in range(start):
if not l: break # End of list.
l=l.tail
return l
else:
# We need to construct a new list.
if step < 1: # Need to instantiate list to deal with -ve step
return LinkedList(list(self)[start:stop:step])
else:
return LinkedList(itertools.islice(iter(self), start, stop, step))
else:
# Non-slice index.
if idx < 0: idx = len(self)+idx
if not self: raise IndexError("list index out of range")
if idx == 0: return self.head
return self.tail[idx-1]
def __mul__(self, n):
if n <= 0: return Nil
l=self
for i in range(n-1): l += self
return l
def __rmul__(self, n): return self * n
# Ideally we should compute the has ourselves rather than construct
# a temporary tuple as below. I haven't impemented this here
def __hash__(self): return hash(tuple(self))
def __eq__(self, other): return self._cmp(other) == 0
def __ne__(self, other): return not self == other
def __lt__(self, other): return self._cmp(other) < 0
def __gt__(self, other): return self._cmp(other) > 0
def __le__(self, other): return self._cmp(other) <= 0
def __ge__(self, other): return self._cmp(other) >= 0
def _cmp(self, other):
"""Acts as cmp(): -1 for self<other, 0 for equal, 1 for greater"""
if not isinstance(other, LinkedList):
return cmp(LinkedList,type(other)) # Arbitrary ordering.
A, B = iter(self), iter(other)
for a,b in itertools.izip(A,B):
if a<b: return -1
elif a > b: return 1
try:
A.next()
return 1 # a has more items.
except StopIteration: pass
try:
B.next()
return -1 # b has more items.
except StopIteration: pass
return 0 # Lists are equal
def __repr__(self):
return "LinkedList([%s])" % ', '.join(map(repr,self))
class EmptyList(LinkedList):
"""A singleton representing an empty list."""
def __new__(cls):
return object.__new__(cls)
def __iter__(self): return iter([])
def __nonzero__(self): return False
@property
def head(self): raise IndexError("End of list")
@property
def tail(self): raise IndexError("End of list")
# Create EmptyList singleton
LinkedList.EmptyList = EmptyList()
del EmptyList
Как сказано в большинстве других ответов, методы экземпляра используют экземпляр класса, тогда как метод класса может использоваться только с именем класса. В Objective-C они определены следующим образом:
@interface MyClass : NSObject
+ (void)aClassMethod;
- (void)anInstanceMethod;
@end
Затем они могут использоваться следующим образом:
[MyClass aClassMethod];
MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];
Некоторые реальные примеры методов класса - это вспомогательные методы для многих классов Foundation, например NSString
] + stringWithFormat:
или NSArray
's + arrayWithArray:
. Методом экземпляра будет метод NSArray
-count
.
Методы класса не могут изменить или узнать значение любой переменной экземпляра. Это должно быть критерием для того, чтобы знать, может ли метод экземпляра быть методом класса.
В Objective-C все методы начинаются с символа «-» или «+». Пример:
@interface MyClass : NSObject
// instance method
- (void) instanceMethod;
+ (void) classMethod;
@end
Символы «+» и «-» указывают, является ли метод class method
или instance method
соответственно.
Разница была бы ясна, если бы мы назвали эти методы. Здесь методы объявлены в MyClass
.
instance method
требуется экземпляр класса:
MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];
Внутри MyClass
другие методы могут вызывать методы экземпляра MyClass
, используя self
:
-(void) someMethod
{
[self instanceMethod];
}
Но, class methods
должен быть вызван для самого класса:
[MyClass classMethod];
Или:
MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];
Это не будет работать:
// Error
[myClass classMethod];
// Error
[self classMethod];
Методы класса обычно используются для создания экземпляров этого класса
Например, [NSString stringWithFormat:@"SomeParameter"];
возвращает экземпляр NSString
с параметром, который ему отправляется. Следовательно, поскольку это метод класса, который возвращает объект своего типа, его также называют вспомогательным методом.
Ответ на ваш вопрос не относится к объекту-c, однако на разных языках методы класса могут называться статическими методами.
Разница между методами класса и методами экземпляра
] Методы класса
Методы экземпляра
Метод экземпляра применяется к экземпляру класса (т. Е. Объекту), тогда как метод класса применяется к самому классу.
В C # метод класса помечен как статический. Методы и свойства, не помеченные как статические, являются методами экземпляра.
class Foo {
public static void ClassMethod() { ... }
public void InstanceMethod() { ... }
}
Как уже говорилось в других ответах, методы экземпляра работают с объектом и имеют доступ к его переменным экземпляра, в то время как метод класса работает с классом в целом и не имеет доступа к конкретным переменным экземпляра (если только вы не передаете экземпляр в качестве параметра).
Хорошим примером метода класса является метод счетного типа, который возвращает общее количество экземпляров класса. Методы класса начинаются с +
, а экземпляры - с -
.
Хорошим примером метода класса является метод счетчика, который возвращает общее количество экземпляров класса. Методы класса начинаются с +
, а экземпляры - с -
.
Хорошим примером метода класса является метод счетчика, который возвращает общее количество экземпляров класса. Методы класса начинаются с +
, а экземпляры - с -
.
Например:
static int numberOfPeople = 0;
@interface MNPerson : NSObject {
int age; //instance variable
}
+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
@end
@implementation MNPerson
- (id)init{
if (self = [super init]){
numberOfPeople++;
age = 0;
}
return self;
}
+ (int)population{
return numberOfPeople;
}
- (int)age{
return age;
}
@end
main.m:
MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(@"Age: %d",[micmoo age]);
NSLog(@"%Number Of people: %d",[MNPerson population]);
Вывод: Возраст: 0 Количество людей: 2
Другой пример: если у вас есть метод, который вы хотите, чтобы пользователь мог вызывать, иногда полезно сделать его методом класса. Например, если у вас есть класс с именем MathFunctions, вы можете сделать это:
+ (int)square:(int)num{
return num * num;
}
Итак, тогда пользователь вызовет:
[MathFunctions square:34];
без необходимости создавать экземпляр класса!
Вы также можете использовать функции класса для возврата автоматически выпущенных объектов , например
+ (NSArray *)arrayWithObject:(id)object
NSArray, который берет объект, помещает его в массив и возвращает автоматически выпущенную версию массива, которая не требует управления памятью, отлично подходит для временных массивов и прочего.
Надеюсь, теперь вы понять, когда и / или почему вам следует использовать методы класса !!
Методы экземпляров работают с экземплярами классов (т. Е. «Объектами»). Методы классов связаны с классами (в большинстве языков для этих парней используется ключевое слово static
).