Strings are fixed length in numpy. What doesn't fit is simply discarded:
np.array('hello', dtype='S4')
# array(b'hell', dtype='|S4')
dtype('S') appears to be equivalent to dtype('S0'):
np.dtype('S').itemsize
# 0
so assigning to that gets your strings truncated at position 0.
If you know the maximum length to expect in advance:
c = np.empty((1,), dtype=', '.join(['i4'] + 9*['S5']))
for i in range(1, 10):
c[0][i] = 'hello'
c
# array([ (-1710610776, b'hello', b'hello', b'hello', b'hello', b'hello', b'hello', b'hello', b'hello', b'hello')],
# dtype=[('f0', '<i4'), ('f1', 'S5'), ('f2', 'S5'), ('f3', 'S5'), ('f4', 'S5'), ('f5', 'S5'), ('f6', 'S5'), ('f7', 'S5'), ('f8', 'S5'), ('f9', 'S5')])
If you need flexible length you can use object dtype:
c = np.empty((1,), dtype=', '.join(['i4'] + 9*['O']))
for i in range(1, 10):
c[0][i] = 'hello world'[:i]
c
# array([ (0, 'h', 'he', 'hel', 'hell', 'hello', 'hello ', 'hello w', 'hello wo', 'hello wor')],
# dtype=[('f0', '<i4'), ('f1', 'O'), ('f2', 'O'), ('f3', 'O'), ('f4', 'O'), ('f5', 'O'), ('f6', 'O'), ('f7', 'O'), ('f8', 'O'), ('f9', 'O')])
If you want fixed length just large enough, have all the records at hand and are not too picky about the exact types you can have numpy work it out for you:
lot = [(5,) + tuple('hello world 2 3 4 5 6 7 8 9'.split()), (8,) + tuple('0 1 2 3 short loooooooong 6 7 8 9'.split())]
lot
# [(5, 'hello', 'world', '2', '3', '4', '5', '6', '7', '8', '9'), (8, '0', '1', '2', '3', 'short', 'loooooooong', '6', '7', '8', '9')]
c = np.rec.fromrecords(lot)
c
# rec.array([(5, 'hello', 'world', '2', '3', '4', '5', '6', '7', '8', '9'),
# (8, '0', '1', '2', '3', 'short', 'loooooooong', '6', '7', '8', '9')],
# dtype=[('f0', '<i8'), ('f1', '<U5'), ('f2', '<U5'), ('f3', '<U1'), ('f4', '<U1'), ('f5', '<U5'), ('f6', '<U11'), ('f7', '<U1'), ('f8', '<U1'), ('f9', '<U1'), ('f10', '<U1')])
dype?x = np.zeros(3, dtype='3int8, float32, (2,3)float64')